From 2167ab94177ee3617b4e0c54774d9ce22609fead Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 16 Mar 2022 20:45:49 +0100 Subject: [PATCH 01/80] Actualiza y afina las dependencias de paquetes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit También normaliza los "traits" para definir temas y módulos usando el mismo criterio visto en SeaORM. --- drust/src/main.rs | 4 ++- pagetop/Cargo.toml | 19 ++++++----- pagetop/src/base/module/admin/mod.rs | 2 +- pagetop/src/base/module/homepage/mod.rs | 2 +- pagetop/src/base/module/user/mod.rs | 2 +- pagetop/src/base/theme/aliner/mod.rs | 2 +- pagetop/src/base/theme/bootsier/mod.rs | 2 +- pagetop/src/base/theme/minimal/mod.rs | 2 +- pagetop/src/core/{global.rs => all.rs} | 36 +++++++-------------- pagetop/src/core/html.rs | 1 + pagetop/src/core/mod.rs | 3 +- pagetop/src/core/module/definition.rs | 2 +- pagetop/src/core/module/mod.rs | 12 +++---- pagetop/src/core/response/page/assets.rs | 13 ++++---- pagetop/src/core/response/page/component.rs | 2 +- pagetop/src/core/response/page/container.rs | 2 +- pagetop/src/core/response/page/page.rs | 17 ++++++---- pagetop/src/core/server/app.rs | 20 ++++++------ pagetop/src/core/server/db.rs | 13 +++----- pagetop/src/core/server/locale.rs | 7 ++-- pagetop/src/core/theme/definition.rs | 6 ++-- pagetop/src/core/theme/mod.rs | 14 ++++---- pagetop/src/lib.rs | 2 -- pagetop/src/locale.rs | 4 +-- pagetop/src/prelude.rs | 2 ++ pagetop/tests/health_check.rs | 9 +++--- 26 files changed, 100 insertions(+), 100 deletions(-) rename pagetop/src/core/{global.rs => all.rs} (53%) create mode 100644 pagetop/src/core/html.rs diff --git a/drust/src/main.rs b/drust/src/main.rs index 6916d3b1..ac96b1ed 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,4 +1,6 @@ +use pagetop::prelude::*; + #[actix_web::main] async fn main() -> std::io::Result<()> { - pagetop::Application::build(None).await?.run()?.await + Application::prepare(essence).await?.run()?.await } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index b828e58f..e6cbc75e 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -27,16 +27,16 @@ categories = [ doc-comment = "0.3.3" downcast-rs = "1.2.0" figlet-rs = "0.1.3" -futures = "0.3" -once_cell = "1.9.0" +futures = "0.3.21" +once_cell = "1.10.0" url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } -tracing = "0.1" -tracing-appender = "0.2" -tracing-subscriber = { version = "0.3", features = ["json", "env-filter"] } -tracing-unwrap = { version = "0.9", default-features = false } +tracing = "0.1.32" +tracing-appender = "0.2.1" +tracing-subscriber = { version = "0.3.9", features = ["json", "env-filter"] } +tracing-unwrap = { version = "0.9.2", default-features = false } tracing-actix-web = "0.2" fluent-templates = "0.6.1" @@ -51,17 +51,20 @@ sycamore = { version = "0.7.1", features = ["ssr"] } serde = { version = "1.0", features = ["derive"] } [dependencies.sea-orm] -version = "0.6" +version = "0.6.0" features = ["debug-print", "macros", "runtime-async-std-native-tls"] default-features = false optional = true [dependencies.sea-schema] -version = "0.5" +version = "0.6.0" features = ["debug-print", "migration"] default-features = false optional = true +[dev-dependencies] +tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } + [features] default = [] mysql = ["sea-orm", "sea-schema", "sea-orm/sqlx-mysql"] diff --git a/pagetop/src/base/module/admin/mod.rs b/pagetop/src/base/module/admin/mod.rs index 0bb1202d..808aa75e 100644 --- a/pagetop/src/base/module/admin/mod.rs +++ b/pagetop/src/base/module/admin/mod.rs @@ -6,7 +6,7 @@ mod summary; pub struct AdminModule; -impl Module for AdminModule { +impl ModuleTrait for AdminModule { fn name(&self) -> &'static str { "admin" } diff --git a/pagetop/src/base/module/homepage/mod.rs b/pagetop/src/base/module/homepage/mod.rs index de4b98ce..b6aac4fe 100644 --- a/pagetop/src/base/module/homepage/mod.rs +++ b/pagetop/src/base/module/homepage/mod.rs @@ -4,7 +4,7 @@ localize!("en-US", "src/base/module/homepage/locales"); pub struct HomepageModule; -impl Module for HomepageModule { +impl ModuleTrait for HomepageModule { fn name(&self) -> &'static str { "homepage" } diff --git a/pagetop/src/base/module/user/mod.rs b/pagetop/src/base/module/user/mod.rs index 7dc3c043..99096377 100644 --- a/pagetop/src/base/module/user/mod.rs +++ b/pagetop/src/base/module/user/mod.rs @@ -7,7 +7,7 @@ mod migration; pub struct UserModule; -impl Module for UserModule { +impl ModuleTrait for UserModule { fn name(&self) -> &'static str { "user" } diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index b678d4b7..18df448f 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -4,7 +4,7 @@ include!(concat!(env!("OUT_DIR"), "/aliner.rs")); pub struct AlinerTheme; -impl Theme for AlinerTheme { +impl ThemeTrait for AlinerTheme { fn name(&self) -> &'static str { "aliner" } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index 3a340a84..dd16d71c 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -6,7 +6,7 @@ localize!("en-US", "src/base/theme/bootsier/locales"); pub struct BootsierTheme; -impl Theme for BootsierTheme { +impl ThemeTrait for BootsierTheme { fn name(&self) -> &'static str { "bootsier" } diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs index c6780005..b3a50906 100644 --- a/pagetop/src/base/theme/minimal/mod.rs +++ b/pagetop/src/base/theme/minimal/mod.rs @@ -2,7 +2,7 @@ use crate::prelude::*; pub struct MinimalTheme; -impl Theme for MinimalTheme { +impl ThemeTrait for MinimalTheme { fn name(&self) -> &'static str { "minimal" } diff --git a/pagetop/src/core/global.rs b/pagetop/src/core/all.rs similarity index 53% rename from pagetop/src/core/global.rs rename to pagetop/src/core/all.rs index dd9aa909..b48e0684 100644 --- a/pagetop/src/core/global.rs +++ b/pagetop/src/core/all.rs @@ -1,21 +1,19 @@ use crate::{Lazy, trace}; -use crate::core::theme::Theme; -use crate::core::module::Module; -use crate::core::response::page::PageContainer; +use crate::core::theme::ThemeTrait; +use crate::core::module::ModuleTrait; use crate::core::server; use std::sync::RwLock; -use std::collections::HashMap; include!(concat!(env!("OUT_DIR"), "/theme.rs")); // ----------------------------------------------------------------------------- -// Temas registrados y tema por defecto. +// Temas registrados y tema predeterminado. // ----------------------------------------------------------------------------- -pub static THEMES: Lazy>> = Lazy::new(|| { - RwLock::new(Vec::new()) -}); +pub static THEMES: Lazy>> = Lazy::new( + || { RwLock::new(Vec::new()) } +); pub fn themes(cfg: &mut server::web::ServiceConfig) { cfg.service(actix_web_static_files::ResourceFiles::new( @@ -32,9 +30,9 @@ pub fn themes(cfg: &mut server::web::ServiceConfig) { // Módulos registrados. // ----------------------------------------------------------------------------- -pub static MODULES: Lazy>> = Lazy::new(|| { - RwLock::new(Vec::new()) -}); +pub static MODULES: Lazy>> = Lazy::new( + || { RwLock::new(Vec::new()) } +); pub fn modules(cfg: &mut server::web::ServiceConfig) { for m in MODULES.read().unwrap().iter() { @@ -43,19 +41,9 @@ pub fn modules(cfg: &mut server::web::ServiceConfig) { } #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub fn run_migrations() { - trace::info!("Checking migrations."); +pub fn migrations() { + trace::info!("Checking migrations"); for m in MODULES.read().unwrap().iter() { - m.migrations( - &*server::db::DBCONN.read().unwrap() - ).expect("Failed to run migrations"); + m.migrations(&*server::db::DBCONN).expect("Failed to run migrations"); } } - -// ----------------------------------------------------------------------------- -// Componentes globales. -// ----------------------------------------------------------------------------- - -pub static COMPONENTS: Lazy>> = Lazy::new( - || { RwLock::new(HashMap::new()) } -); diff --git a/pagetop/src/core/html.rs b/pagetop/src/core/html.rs new file mode 100644 index 00000000..ba885bb3 --- /dev/null +++ b/pagetop/src/core/html.rs @@ -0,0 +1 @@ +pub use maud::{DOCTYPE, Markup, PreEscaped, html}; diff --git a/pagetop/src/core/mod.rs b/pagetop/src/core/mod.rs index 26618959..8db86b83 100644 --- a/pagetop/src/core/mod.rs +++ b/pagetop/src/core/mod.rs @@ -1,7 +1,8 @@ pub use actix_web::dev::Server; -mod global; +mod all; +pub mod html; pub mod theme; pub mod module; pub mod response; diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/core/module/definition.rs index 7dc6252b..011ef083 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/core/module/definition.rs @@ -4,7 +4,7 @@ use crate::core::server; use crate::db; /// Los módulos deben implementar este *trait*. -pub trait Module: Send + Sync { +pub trait ModuleTrait: Send + Sync { fn name(&self) -> &'static str; fn fullname(&self) -> String; diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module/mod.rs index 439cff79..2a42352a 100644 --- a/pagetop/src/core/module/mod.rs +++ b/pagetop/src/core/module/mod.rs @@ -1,14 +1,14 @@ -use crate::core::global; +use crate::core::all; mod definition; -pub use definition::Module; +pub use definition::ModuleTrait; -pub fn register_module(m: &'static (dyn Module + 'static)) { - global::MODULES.write().unwrap().push(m); +pub fn register_module(m: &'static (dyn ModuleTrait + 'static)) { + all::MODULES.write().unwrap().push(m); } -pub fn find_module(name: &str) -> Option<&'static (dyn Module + 'static)> { - let modules = global::MODULES.write().unwrap(); +pub fn find_module(name: &str) -> Option<&'static (dyn ModuleTrait + 'static)> { + let modules = all::MODULES.write().unwrap(); match modules.iter().find(|t| t.name() == name) { Some(module) => Some(*module), _ => None, diff --git a/pagetop/src/core/response/page/assets.rs b/pagetop/src/core/response/page/assets.rs index 11cdd35c..2bd96fc2 100644 --- a/pagetop/src/core/response/page/assets.rs +++ b/pagetop/src/core/response/page/assets.rs @@ -1,10 +1,11 @@ use crate::{Lazy, base}; use crate::config::SETTINGS; -use crate::core::global; -use crate::core::theme::{Markup, PreEscaped, Theme, find_theme, html}; +use crate::core::all; +use crate::core::html::{Markup, PreEscaped, html}; +use crate::core::theme::*; -static DEFAULT_THEME: Lazy<&dyn Theme> = Lazy::new(|| { - for t in global::THEMES.read().unwrap().iter() { +static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { + for t in all::THEMES.read().unwrap().iter() { if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() { return *t; } @@ -184,7 +185,7 @@ impl JavaScript { // ----------------------------------------------------------------------------- pub struct PageAssets { - theme : &'static dyn Theme, + theme : &'static dyn ThemeTrait, favicon : Option, metadata : Vec<(String, String)>, stylesheets: Vec, @@ -259,7 +260,7 @@ impl PageAssets { /// Assets GETTERS. - pub fn theme(&mut self) -> &'static dyn Theme { + pub fn theme(&mut self) -> &'static dyn ThemeTrait { self.theme } diff --git a/pagetop/src/core/response/page/component.rs b/pagetop/src/core/response/page/component.rs index 1472ffe2..78925468 100644 --- a/pagetop/src/core/response/page/component.rs +++ b/pagetop/src/core/response/page/component.rs @@ -1,4 +1,4 @@ -use crate::core::theme::{Markup, html}; +use crate::core::html::{Markup, html}; use crate::core::response::page::PageAssets; use downcast_rs::{Downcast, impl_downcast}; diff --git a/pagetop/src/core/response/page/container.rs b/pagetop/src/core/response/page/container.rs index 6bf5e56a..4a577b2d 100644 --- a/pagetop/src/core/response/page/container.rs +++ b/pagetop/src/core/response/page/container.rs @@ -1,4 +1,4 @@ -use crate::core::theme::{Markup, html}; +use crate::core::html::{Markup, html}; use crate::core::response::page::{PageAssets, PageComponent, render_component}; use std::sync::Arc; diff --git a/pagetop/src/core/response/page/page.rs b/pagetop/src/core/response/page/page.rs index 8052683d..d47a33f1 100644 --- a/pagetop/src/core/response/page/page.rs +++ b/pagetop/src/core/response/page/page.rs @@ -1,12 +1,17 @@ use crate::{Lazy, trace, util}; use crate::config::SETTINGS; -use crate::core::{global, server}; -use crate::core::theme::{DOCTYPE, Markup, html}; +use crate::core::html::{DOCTYPE, Markup, html}; use crate::core::response::page::{PageAssets, PageComponent, PageContainer}; +use crate::core::server; use std::borrow::Cow; +use std::sync::RwLock; use std::collections::HashMap; +static COMPONENTS: Lazy>> = Lazy::new(|| { + RwLock::new(HashMap::new()) +}); + static DEFAULT_LANGUAGE: Lazy> = Lazy::new(|| { let language = SETTINGS.app.language[..2].to_lowercase(); if !language.is_empty() { @@ -25,9 +30,9 @@ static DEFAULT_DIRECTION: Lazy> = Lazy::new(|| { "" => None, _ => { trace::warn!( - "Text direction \"{}\" not valid. {}.", + "Text direction \"{}\" not valid, {}", SETTINGS.app.direction, - "Check the settings file" + "check the settings file" ); None } @@ -63,7 +68,7 @@ impl<'a> Page<'a> { description : None, body_classes: "body".into(), assets : PageAssets::new(), - regions : global::COMPONENTS.read().unwrap().clone(), + regions : COMPONENTS.read().unwrap().clone(), template : "default".to_owned(), } } @@ -208,7 +213,7 @@ pub fn render_component( } pub fn add_component_to(region: &'static str, component: impl PageComponent) { - let mut hmap = global::COMPONENTS.write().unwrap(); + let mut hmap = COMPONENTS.write().unwrap(); if let Some(regions) = hmap.get_mut(region) { regions.add(component); } else { diff --git a/pagetop/src/core/server/app.rs b/pagetop/src/core/server/app.rs index 7338aa3b..cbca9979 100644 --- a/pagetop/src/core/server/app.rs +++ b/pagetop/src/core/server/app.rs @@ -1,6 +1,6 @@ use crate::{Lazy, base, trace}; use crate::config::SETTINGS; -use crate::core::{Server, global, server}; +use crate::core::{Server, all, server}; use crate::core::theme::register_theme; use crate::core::module::register_module; @@ -11,8 +11,12 @@ pub struct Application { server: Server, } +pub fn essence() { + trace::info!("No bootstrap configured"); +} + impl Application { - pub async fn build(bootstrap: Option) -> Result { + pub async fn prepare(bootstrap: fn()) -> Result { // Imprime un rótulo de presentación (opcional). if SETTINGS.app.startup_banner.to_lowercase() != "off" { let figfont = figlet_rs::FIGfont::from_content( @@ -61,10 +65,8 @@ impl Application { register_module(&base::module::user::UserModule); // Ejecuta la función de inicio de la aplicación. - if bootstrap != None { - trace::info!("Calling application bootstrap."); - let _ = &(bootstrap.unwrap())(); - } + trace::info!("Calling application bootstrap"); + let _ = &bootstrap(); // Registra el módulo para la página de inicio de PageTop. // Al ser el último, puede sobrecargarse con la función de inicio. @@ -72,15 +74,15 @@ impl Application { // Comprueba actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - global::run_migrations(); + all::migrations(); // Prepara el servidor web. let server = server::HttpServer::new(move || { server::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(NormalizePath::new(TrailingSlash::Trim)) - .configure(&global::themes) - .configure(&global::modules) + .configure(&all::themes) + .configure(&all::modules) }) .bind(format!("{}:{}", &SETTINGS.webserver.bind_address, diff --git a/pagetop/src/core/server/db.rs b/pagetop/src/core/server/db.rs index 8c5c9f1f..9d196970 100644 --- a/pagetop/src/core/server/db.rs +++ b/pagetop/src/core/server/db.rs @@ -1,13 +1,12 @@ use crate::{Lazy, db, run_now, trace}; use crate::config::SETTINGS; -use std::sync::RwLock; use sea_orm::{ConnectOptions, Database}; use tracing_unwrap::ResultExt; -pub static DBCONN: Lazy> = Lazy::new(|| { +pub static DBCONN: Lazy = Lazy::new(|| { trace::info!( - "Connecting to database \"{}\" using a pool of {} connections.", + "Connecting to database \"{}\" using a pool of {} connections", &SETTINGS.database.db_name, &SETTINGS.database.max_pool_size ); @@ -41,20 +40,18 @@ pub static DBCONN: Lazy> = Lazy::new(|| { ).as_str()).unwrap(), _ => { trace::error!( - "Unrecognized database type \"{}\".", + "Unrecognized database type \"{}\"", &SETTINGS.database.db_type ); db::DbUri::parse("").unwrap() } }; - let db_conn = run_now( + run_now( Database::connect::({ let mut db_opt = ConnectOptions::new(db_uri.to_string()); db_opt.max_connections(SETTINGS.database.max_pool_size); db_opt.into() }) - ).expect_or_log("Failed to connect to database"); - - RwLock::new(db_conn) + ).expect_or_log("Failed to connect to database") }); diff --git a/pagetop/src/core/server/locale.rs b/pagetop/src/core/server/locale.rs index 8bc6fc10..59fc8468 100644 --- a/pagetop/src/core/server/locale.rs +++ b/pagetop/src/core/server/locale.rs @@ -11,11 +11,12 @@ pub static LANGID: Lazy = Lazy::new(|| { Ok(language) => language, Err(_) => { trace::warn!( - "Failed to parse language \"{}\". {}. {}. {}.", + "{}, {} \"{}\"! {}, {}", + "Failed to parse language", + "unrecognized Unicode Language Identifier", SETTINGS.app.language, - "Unrecognized Unicode Language Identifier", "Using \"en-US\"", - "Check the settings file", + "check the settings file", ); "en-US".parse().unwrap() } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 12d9e05f..eb67ec10 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -1,11 +1,11 @@ use crate::config::SETTINGS; -use crate::core::server; -use crate::core::theme::{Markup, html}; +use crate::core::html::{Markup, html}; use crate::core::response::page::{Page, PageAssets, PageComponent}; +use crate::core::server; use crate::base::component::Chunck; /// Los temas deben implementar este "trait". -pub trait Theme: Send + Sync { +pub trait ThemeTrait: Send + Sync { fn name(&self) -> &'static str; fn fullname(&self) -> String; diff --git a/pagetop/src/core/theme/mod.rs b/pagetop/src/core/theme/mod.rs index 8292ade6..e83f4307 100644 --- a/pagetop/src/core/theme/mod.rs +++ b/pagetop/src/core/theme/mod.rs @@ -1,16 +1,14 @@ -use crate::core::global; - -pub use maud::{DOCTYPE, Markup, PreEscaped, html}; +use crate::core::all; mod definition; -pub use definition::Theme; +pub use definition::ThemeTrait; -pub fn register_theme(t: &'static (dyn Theme + 'static)) { - global::THEMES.write().unwrap().push(t); +pub fn register_theme(t: &'static (dyn ThemeTrait + 'static)) { + all::THEMES.write().unwrap().push(t); } -pub fn find_theme(name: &str) -> Option<&'static (dyn Theme + 'static)> { - let themes = global::THEMES.write().unwrap(); +pub fn find_theme(name: &str) -> Option<&'static (dyn ThemeTrait + 'static)> { + let themes = all::THEMES.write().unwrap(); match themes.iter().find(|t| t.name() == name) { Some(theme) => Some(*theme), _ => None, diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index b8485f96..daf0577d 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -20,5 +20,3 @@ pub mod base; // Temas, Módulos y Componentes base. pub mod util; // Macros y funciones útiles. pub mod prelude; // Re-exporta recursos comunes. - -pub use crate::core::server::app::Application; diff --git a/pagetop/src/locale.rs b/pagetop/src/locale.rs index 22a01ba6..eac11472 100644 --- a/pagetop/src/locale.rs +++ b/pagetop/src/locale.rs @@ -37,8 +37,8 @@ macro_rules! localize { fn e( key: &str, args: &std::collections::HashMap - ) -> crate::core::theme::PreEscaped { - crate::core::theme::PreEscaped( + ) -> crate::core::html::PreEscaped { + crate::core::html::PreEscaped( LOCALES.lookup_with_args(&LANGID, key, args) ) } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index f0a4b031..1dd8bd79 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -8,10 +8,12 @@ pub use crate::localize; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::{db, db_migrations}; +pub use crate::core::html::*; pub use crate::core::theme::*; pub use crate::core::module::*; pub use crate::core::response::page::*; pub use crate::core::server; +pub use crate::core::server::app::{Application, essence}; pub use crate::base::component::*; diff --git a/pagetop/tests/health_check.rs b/pagetop/tests/health_check.rs index 0c309bea..dd980796 100644 --- a/pagetop/tests/health_check.rs +++ b/pagetop/tests/health_check.rs @@ -1,7 +1,8 @@ -use pagetop::core::server; - -fn spawn_app() { - let server = server::run(None).expect("Failed to bind address"); +async fn spawn_app() { + let server = pagetop::Application::prepare(None) + .await? + .run()? + .expect("Failed to prepare server"); let _ = tokio::spawn(server); } From 58afd1f2582fa2b62357d345437199d3c17e150d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 17 Mar 2022 19:41:41 +0100 Subject: [PATCH 02/80] =?UTF-8?q?Corrige=20ejecuci=C3=B3n=20de=20las=20mig?= =?UTF-8?q?raciones=20en=20m=C3=B3dulos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/module/user/migration/mod.rs | 11 ---------- pagetop/src/base/module/user/mod.rs | 8 ++++--- pagetop/src/config.rs | 10 ++++----- pagetop/src/core/all.rs | 22 ++++++++++++++----- pagetop/src/core/module/definition.rs | 4 ++-- pagetop/src/core/server/app.rs | 2 +- pagetop/src/db.rs | 10 +++------ pagetop/src/prelude.rs | 2 +- pagetop/src/util.rs | 4 ++-- 9 files changed, 35 insertions(+), 38 deletions(-) diff --git a/pagetop/src/base/module/user/migration/mod.rs b/pagetop/src/base/module/user/migration/mod.rs index 8b9167a6..60836980 100644 --- a/pagetop/src/base/module/user/migration/mod.rs +++ b/pagetop/src/base/module/user/migration/mod.rs @@ -1,12 +1 @@ -use crate::db::migration::*; - pub mod m20220312_000001_create_table_user; - -pub struct Migrator; - -#[async_trait::async_trait] -impl MigratorTrait for Migrator { - fn migrations() -> Vec> { - vec![Box::new(m20220312_000001_create_table_user::Migration)] - } -} diff --git a/pagetop/src/base/module/user/mod.rs b/pagetop/src/base/module/user/mod.rs index 99096377..362961eb 100644 --- a/pagetop/src/base/module/user/mod.rs +++ b/pagetop/src/base/module/user/mod.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -localize!("en-US", "src/base/module/user/locales"); +localize!("src/base/module/user/locales"); mod entity; mod migration; @@ -24,8 +24,10 @@ impl ModuleTrait for UserModule { cfg.route("/user/login", server::web::get().to(login)); } - fn migrations(&self, dbconn: &db::DbConn) -> Result<(), db::DbErr> { - db_migrations!(dbconn) + fn migrations(&self) -> Vec> { + vec![ + boxed_migration!(m20220312_000001_create_table_user) + ] } } diff --git a/pagetop/src/config.rs b/pagetop/src/config.rs index fedffc21..27dbb275 100644 --- a/pagetop/src/config.rs +++ b/pagetop/src/config.rs @@ -45,15 +45,15 @@ pub static CONFIG: Lazy = Lazy::new(|| { /// seguros. Produce un *panic!* en caso de asignaciones no válidas. macro_rules! config_map { ( - $COMM:expr, - $CONF:ident, - $TYPE:tt + $doc:expr, + $SETTINGS:ident, + $Type:tt $(, $key:expr => $value:expr)* ) => { $crate::doc_comment! { - concat!($COMM), + concat!($doc), - pub static $CONF: $crate::Lazy<$TYPE> = $crate::Lazy::new(|| { + pub static $SETTINGS: $crate::Lazy<$Type> = $crate::Lazy::new(|| { let mut settings = $crate::config::CONFIG.clone(); $( settings.set_default($key, $value).unwrap(); diff --git a/pagetop/src/core/all.rs b/pagetop/src/core/all.rs index b48e0684..20df22bd 100644 --- a/pagetop/src/core/all.rs +++ b/pagetop/src/core/all.rs @@ -1,4 +1,5 @@ -use crate::{Lazy, trace}; +use crate::{Lazy, run_now}; +use crate::db::migration::*; use crate::core::theme::ThemeTrait; use crate::core::module::ModuleTrait; use crate::core::server; @@ -41,9 +42,18 @@ pub fn modules(cfg: &mut server::web::ServiceConfig) { } #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub fn migrations() { - trace::info!("Checking migrations"); - for m in MODULES.read().unwrap().iter() { - m.migrations(&*server::db::DBCONN).expect("Failed to run migrations"); - } +pub fn run_migrations() { + run_now({ + struct Migrator; + impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + let mut migrations = vec![]; + for m in MODULES.read().unwrap().iter() { + migrations.append(&mut m.migrations()); + } + migrations + } + } + Migrator::up(&server::db::DBCONN, None) + }).unwrap(); } diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/core/module/definition.rs index 011ef083..c50cace3 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/core/module/definition.rs @@ -19,7 +19,7 @@ pub trait ModuleTrait: Send + Sync { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[allow(unused_variables)] - fn migrations(&self, dbconn: &db::DbConn) -> Result<(), db::DbErr> { - Ok(()) + fn migrations(&self) -> Vec> { + vec![] } } diff --git a/pagetop/src/core/server/app.rs b/pagetop/src/core/server/app.rs index cbca9979..74e1690d 100644 --- a/pagetop/src/core/server/app.rs +++ b/pagetop/src/core/server/app.rs @@ -74,7 +74,7 @@ impl Application { // Comprueba actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - all::migrations(); + all::run_migrations(); // Prepara el servidor web. let server = server::HttpServer::new(move || { diff --git a/pagetop/src/db.rs b/pagetop/src/db.rs index b487cc19..d68a5aac 100644 --- a/pagetop/src/db.rs +++ b/pagetop/src/db.rs @@ -14,12 +14,8 @@ pub mod migration { } #[macro_export] -macro_rules! db_migrations { - ( $DBCONN:ident ) => {{ - $crate::run_now({ - use $crate::db::migration::MigratorTrait; - - migration::Migrator::up($DBCONN, None) - }) +macro_rules! boxed_migration { + ( $migration_module:ident ) => {{ + Box::new(migration::$migration_module::Migration) }}; } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 1dd8bd79..18d160ce 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -6,7 +6,7 @@ pub use crate::trace; pub use crate::localize; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub use crate::{db, db_migrations}; +pub use crate::{db, boxed_migration}; pub use crate::core::html::*; pub use crate::core::theme::*; diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index c56d2146..3fff0a23 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -9,10 +9,10 @@ /// ]; /// ``` macro_rules! args { - ( $($KEY:expr => $VALUE:expr),* ) => {{ + ( $($key:expr => $value:expr),* ) => {{ let mut a = std::collections::HashMap::new(); $( - a.insert(String::from($KEY), $VALUE.into()); + a.insert(String::from($key), $value.into()); )* a }}; From 516d9683da657176dbd671ce669e4c26b2d4acdd Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 17 Mar 2022 19:43:42 +0100 Subject: [PATCH 03/80] Modifica y predetermina los locales para en-US --- pagetop/src/base/module/admin/mod.rs | 2 +- pagetop/src/base/module/homepage/mod.rs | 2 +- pagetop/src/base/theme/bootsier/mod.rs | 2 +- pagetop/src/locale.rs | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pagetop/src/base/module/admin/mod.rs b/pagetop/src/base/module/admin/mod.rs index 808aa75e..e9b58703 100644 --- a/pagetop/src/base/module/admin/mod.rs +++ b/pagetop/src/base/module/admin/mod.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -localize!("en-US", "src/base/module/admin/locales"); +localize!("src/base/module/admin/locales"); mod summary; diff --git a/pagetop/src/base/module/homepage/mod.rs b/pagetop/src/base/module/homepage/mod.rs index b6aac4fe..6b3b9741 100644 --- a/pagetop/src/base/module/homepage/mod.rs +++ b/pagetop/src/base/module/homepage/mod.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -localize!("en-US", "src/base/module/homepage/locales"); +localize!("src/base/module/homepage/locales"); pub struct HomepageModule; diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index dd16d71c..3c4176f0 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -2,7 +2,7 @@ use crate::prelude::*; include!(concat!(env!("OUT_DIR"), "/bootsier.rs")); -localize!("en-US", "src/base/theme/bootsier/locales"); +localize!("src/base/theme/bootsier/locales"); pub struct BootsierTheme; diff --git a/pagetop/src/locale.rs b/pagetop/src/locale.rs index eac11472..a5a136c2 100644 --- a/pagetop/src/locale.rs +++ b/pagetop/src/locale.rs @@ -5,15 +5,15 @@ pub use fluent_templates::fluent_bundle::FluentValue; #[macro_export] /// Permite integrar fácilmente localización en temas, módulos y componentes. macro_rules! localize { - ( $DEF_LANGID:literal, $locales:literal $(, $core_locales:literal)? ) => { + ( $dir_locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; use $crate::core::server::locale::LANGID; static_locale! { static LOCALES = { - locales: $locales, + locales: $dir_locales, $( core_locales: $core_locales, )? - fallback_language: $DEF_LANGID, + fallback_language: "en-US", // Elimina las marcas Unicode que delimitan los argumentos. customise: |bundle| bundle.set_use_isolating(false), @@ -37,8 +37,8 @@ macro_rules! localize { fn e( key: &str, args: &std::collections::HashMap - ) -> crate::core::html::PreEscaped { - crate::core::html::PreEscaped( + ) -> $crate::core::html::PreEscaped { + $crate::core::html::PreEscaped( LOCALES.lookup_with_args(&LANGID, key, args) ) } From fbc6ab2adfab1aa4e7da8d3c832d5850ea775366 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 19 Mar 2022 20:10:51 +0100 Subject: [PATCH 04/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 3 + drust/Cargo.toml | 3 + drust/src/main.rs | 8 +- pagetop-admin/Cargo.toml | 17 +++ pagetop-admin/src/lib.rs | 24 ++++ .../src}/locales/en-US/admin.ftl | 0 .../src}/locales/es-ES/admin.ftl | 0 .../admin => pagetop-admin/src}/summary.rs | 4 +- pagetop-node/Cargo.toml | 16 +++ pagetop-node/src/lib.rs | 39 +++++++ pagetop-node/src/locales/en-US/homepage.ftl | 2 + pagetop-node/src/locales/es-ES/homepage.ftl | 2 + ...m20220316_000001_create_table_node_type.rs | 90 ++++++++++++++ .../m20220316_000002_create_table_node.rs | 110 ++++++++++++++++++ ...0220316_000003_create_table_node_access.rs | 70 +++++++++++ ...20316_000004_create_table_node_revision.rs | 90 ++++++++++++++ pagetop-node/src/migration/mod.rs | 4 + pagetop-user/Cargo.toml | 22 ++++ .../user => pagetop-user/src}/entity/mod.rs | 0 .../user => pagetop-user/src}/entity/user.rs | 0 .../user/mod.rs => pagetop-user/src/lib.rs | 14 +-- .../src}/locales/en-US/homepage.ftl | 0 .../src}/locales/es-ES/homepage.ftl | 0 .../m20220312_000001_create_table_user.rs | 0 .../src}/migration/mod.rs | 0 pagetop/Cargo.toml | 2 +- ...RTER.Cargo.toml => STARTER.bin.Cargo.toml} | 5 + pagetop/STARTER.lib.Cargo.toml | 29 +++++ pagetop/src/{core => }/all.rs | 13 +-- .../server/app.rs => app/application.rs} | 35 +++--- pagetop/src/{core/server => app}/db.rs | 0 .../{core/server => app}/figfonts/slant.flf | 0 .../{core/server => app}/figfonts/small.flf | 0 .../{core/server => app}/figfonts/speed.flf | 0 .../server => app}/figfonts/starwars.flf | 0 pagetop/src/{core/server => app}/locale.rs | 0 pagetop/src/{core/server => app}/mod.rs | 3 +- pagetop/src/{core/server => app}/tracing.rs | 0 pagetop/src/base/mod.rs | 5 - pagetop/src/base/module/admin/mod.rs | 28 ----- pagetop/src/base/module/mod.rs | 5 - pagetop/src/base/theme/mod.rs | 3 - pagetop/src/{base => }/component/block.rs | 0 pagetop/src/{base => }/component/chunck.rs | 0 pagetop/src/{base => }/component/container.rs | 0 .../src/{base => }/component/form/button.rs | 0 pagetop/src/{base => }/component/form/date.rs | 0 pagetop/src/{base => }/component/form/form.rs | 0 .../src/{base => }/component/form/hidden.rs | 0 .../src/{base => }/component/form/input.rs | 0 pagetop/src/{base => }/component/form/mod.rs | 0 pagetop/src/{base => }/component/menu.rs | 0 pagetop/src/{base => }/component/mod.rs | 0 pagetop/src/core/mod.rs | 9 -- pagetop/src/core/module/mod.rs | 16 --- pagetop/src/{core => }/html.rs | 0 pagetop/src/lib.rs | 12 +- pagetop/src/locale.rs | 6 +- pagetop/src/{core => }/module/definition.rs | 19 ++- .../homepage/locales/en-US/homepage.ftl | 0 .../homepage/locales/es-ES/homepage.ftl | 0 pagetop/src/{base => }/module/homepage/mod.rs | 12 +- pagetop/src/module/mod.rs | 17 +++ pagetop/src/prelude.rs | 15 +-- pagetop/src/{core => }/response/mod.rs | 0 .../src/{core => }/response/page/assets.rs | 9 +- .../src/{core => }/response/page/component.rs | 4 +- .../src/{core => }/response/page/container.rs | 4 +- pagetop/src/{core => }/response/page/mod.rs | 0 pagetop/src/{core => }/response/page/page.rs | 9 +- pagetop/src/{base => }/theme/aliner/mod.rs | 2 +- .../theme/bootsier/locales/en-US/bootsier.ftl | 0 .../theme/bootsier/locales/es-ES/bootsier.ftl | 0 pagetop/src/{base => }/theme/bootsier/mod.rs | 10 +- pagetop/src/{core => }/theme/definition.rs | 12 +- pagetop/src/{base => }/theme/minimal/mod.rs | 0 pagetop/src/{core => }/theme/mod.rs | 10 +- 77 files changed, 651 insertions(+), 161 deletions(-) create mode 100644 pagetop-admin/Cargo.toml create mode 100644 pagetop-admin/src/lib.rs rename {pagetop/src/base/module/admin => pagetop-admin/src}/locales/en-US/admin.ftl (100%) rename {pagetop/src/base/module/admin => pagetop-admin/src}/locales/es-ES/admin.ftl (100%) rename {pagetop/src/base/module/admin => pagetop-admin/src}/summary.rs (95%) create mode 100644 pagetop-node/Cargo.toml create mode 100644 pagetop-node/src/lib.rs create mode 100644 pagetop-node/src/locales/en-US/homepage.ftl create mode 100644 pagetop-node/src/locales/es-ES/homepage.ftl create mode 100644 pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs create mode 100644 pagetop-node/src/migration/m20220316_000002_create_table_node.rs create mode 100644 pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs create mode 100644 pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs create mode 100644 pagetop-node/src/migration/mod.rs create mode 100644 pagetop-user/Cargo.toml rename {pagetop/src/base/module/user => pagetop-user/src}/entity/mod.rs (100%) rename {pagetop/src/base/module/user => pagetop-user/src}/entity/user.rs (100%) rename pagetop/src/base/module/user/mod.rs => pagetop-user/src/lib.rs (80%) rename {pagetop/src/base/module/user => pagetop-user/src}/locales/en-US/homepage.ftl (100%) rename {pagetop/src/base/module/user => pagetop-user/src}/locales/es-ES/homepage.ftl (100%) rename {pagetop/src/base/module/user => pagetop-user/src}/migration/m20220312_000001_create_table_user.rs (100%) rename {pagetop/src/base/module/user => pagetop-user/src}/migration/mod.rs (100%) rename pagetop/{STARTER.Cargo.toml => STARTER.bin.Cargo.toml} (88%) create mode 100644 pagetop/STARTER.lib.Cargo.toml rename pagetop/src/{core => }/all.rs (83%) rename pagetop/src/{core/server/app.rs => app/application.rs} (73%) rename pagetop/src/{core/server => app}/db.rs (100%) rename pagetop/src/{core/server => app}/figfonts/slant.flf (100%) rename pagetop/src/{core/server => app}/figfonts/small.flf (100%) rename pagetop/src/{core/server => app}/figfonts/speed.flf (100%) rename pagetop/src/{core/server => app}/figfonts/starwars.flf (100%) rename pagetop/src/{core/server => app}/locale.rs (100%) rename pagetop/src/{core/server => app}/mod.rs (81%) rename pagetop/src/{core/server => app}/tracing.rs (100%) delete mode 100644 pagetop/src/base/mod.rs delete mode 100644 pagetop/src/base/module/admin/mod.rs delete mode 100644 pagetop/src/base/module/mod.rs delete mode 100644 pagetop/src/base/theme/mod.rs rename pagetop/src/{base => }/component/block.rs (100%) rename pagetop/src/{base => }/component/chunck.rs (100%) rename pagetop/src/{base => }/component/container.rs (100%) rename pagetop/src/{base => }/component/form/button.rs (100%) rename pagetop/src/{base => }/component/form/date.rs (100%) rename pagetop/src/{base => }/component/form/form.rs (100%) rename pagetop/src/{base => }/component/form/hidden.rs (100%) rename pagetop/src/{base => }/component/form/input.rs (100%) rename pagetop/src/{base => }/component/form/mod.rs (100%) rename pagetop/src/{base => }/component/menu.rs (100%) rename pagetop/src/{base => }/component/mod.rs (100%) delete mode 100644 pagetop/src/core/mod.rs delete mode 100644 pagetop/src/core/module/mod.rs rename pagetop/src/{core => }/html.rs (100%) rename pagetop/src/{core => }/module/definition.rs (56%) rename pagetop/src/{base => }/module/homepage/locales/en-US/homepage.ftl (100%) rename pagetop/src/{base => }/module/homepage/locales/es-ES/homepage.ftl (100%) rename pagetop/src/{base => }/module/homepage/mod.rs (88%) create mode 100644 pagetop/src/module/mod.rs rename pagetop/src/{core => }/response/mod.rs (100%) rename pagetop/src/{core => }/response/page/assets.rs (98%) rename pagetop/src/{core => }/response/page/component.rs (90%) rename pagetop/src/{core => }/response/page/container.rs (86%) rename pagetop/src/{core => }/response/page/mod.rs (100%) rename pagetop/src/{core => }/response/page/page.rs (96%) rename pagetop/src/{base => }/theme/aliner/mod.rs (90%) rename pagetop/src/{base => }/theme/bootsier/locales/en-US/bootsier.ftl (100%) rename pagetop/src/{base => }/theme/bootsier/locales/es-ES/bootsier.ftl (100%) rename pagetop/src/{base => }/theme/bootsier/mod.rs (88%) rename pagetop/src/{core => }/theme/definition.rs (89%) rename pagetop/src/{base => }/theme/minimal/mod.rs (100%) rename pagetop/src/{core => }/theme/mod.rs (58%) diff --git a/Cargo.toml b/Cargo.toml index 2369a8da..00ab4e13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,4 +2,7 @@ members = [ "drust", "pagetop", + "pagetop-admin", + "pagetop-user", + "pagetop-node", ] \ No newline at end of file diff --git a/drust/Cargo.toml b/drust/Cargo.toml index dd0bfdc5..88ebabde 100644 --- a/drust/Cargo.toml +++ b/drust/Cargo.toml @@ -19,3 +19,6 @@ default-features = false [dependencies] actix-web = "3.3.3" +pagetop-admin = { path = "../pagetop-admin" } +pagetop-user = { path = "../pagetop-user" } +pagetop-node = { path = "../pagetop-node" } diff --git a/drust/src/main.rs b/drust/src/main.rs index ac96b1ed..e51f5311 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,6 +1,12 @@ use pagetop::prelude::*; +fn bootstrap() { + register_module(&pagetop_admin::AdminModule); + register_module(&pagetop_user::UserModule); + register_module(&pagetop_node::NodeModule); +} + #[actix_web::main] async fn main() -> std::io::Result<()> { - Application::prepare(essence).await?.run()?.await + Application::prepare(bootstrap).await?.run()?.await } diff --git a/pagetop-admin/Cargo.toml b/pagetop-admin/Cargo.toml new file mode 100644 index 00000000..1bff0edd --- /dev/null +++ b/pagetop-admin/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "pagetop-admin" +version = "0.0.1" +edition = "2021" + +authors = [ + "Manuel Cillero " +] +description = """\ + Allows content to be submitted to the site and displayed on pages.\ +""" +homepage = "https://suitepro.cillero.es/projects/drust" +repository = "https://gitlab.com/manuelcillero/drust" + +[dependencies] +pagetop = { path = "../pagetop" } +maud = { version = "0.23.0" } diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs new file mode 100644 index 00000000..e3ad0337 --- /dev/null +++ b/pagetop-admin/src/lib.rs @@ -0,0 +1,24 @@ +use pagetop::prelude::*; + +localize!("src/locales"); + +mod summary; + +pub struct AdminModule; + +impl ModuleTrait for AdminModule { + fn fullname(&self) -> String { + l("module_fullname") + } + + fn description(&self) -> Option { + Some(l("module_description")) + } + + fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + cfg.service( + app::web::scope("/admin") + .route("", app::web::get().to(summary::summary)) + ); + } +} diff --git a/pagetop/src/base/module/admin/locales/en-US/admin.ftl b/pagetop-admin/src/locales/en-US/admin.ftl similarity index 100% rename from pagetop/src/base/module/admin/locales/en-US/admin.ftl rename to pagetop-admin/src/locales/en-US/admin.ftl diff --git a/pagetop/src/base/module/admin/locales/es-ES/admin.ftl b/pagetop-admin/src/locales/es-ES/admin.ftl similarity index 100% rename from pagetop/src/base/module/admin/locales/es-ES/admin.ftl rename to pagetop-admin/src/locales/es-ES/admin.ftl diff --git a/pagetop/src/base/module/admin/summary.rs b/pagetop-admin/src/summary.rs similarity index 95% rename from pagetop/src/base/module/admin/summary.rs rename to pagetop-admin/src/summary.rs index cee26c22..79bf426e 100644 --- a/pagetop/src/base/module/admin/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; +use pagetop::prelude::*; use super::l; -pub async fn summary() -> server::Result { +pub async fn summary() -> app::Result { let top_menu = Menu::prepare() .add(MenuItem::label(l("module_fullname").as_str())) .add(MenuItem::link("Opción 2", "https://www.google.es")) diff --git a/pagetop-node/Cargo.toml b/pagetop-node/Cargo.toml new file mode 100644 index 00000000..36b43d39 --- /dev/null +++ b/pagetop-node/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "pagetop-node" +version = "0.0.1" +edition = "2021" + +authors = [ + "Manuel Cillero " +] +description = """\ + Allows content to be submitted to the site and displayed on pages.\ +""" +homepage = "https://suitepro.cillero.es/projects/drust" +repository = "https://gitlab.com/manuelcillero/drust" + +[dependencies] +pagetop = { path = "../pagetop" } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs new file mode 100644 index 00000000..af6d8b3f --- /dev/null +++ b/pagetop-node/src/lib.rs @@ -0,0 +1,39 @@ +use pagetop::prelude::*; + +localize!("src/locales"); + +//mod entity; +mod migration; + +pub struct NodeModule; + +impl ModuleTrait for NodeModule { + fn fullname(&self) -> String { + l("module_fullname") + } + + fn description(&self) -> Option { + Some(l("module_description")) + } + + fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + cfg.route("/node", app::web::get().to(node)); + } + + fn migrations(&self) -> Vec> { + vec![ + boxed_migration!(m20220316_000001_create_table_node_type), + boxed_migration!(m20220316_000002_create_table_node), + boxed_migration!(m20220316_000003_create_table_node_access), + boxed_migration!(m20220316_000004_create_table_node_revision), + ] + } +} + +async fn node() -> app::Result { + Page::prepare() + .with_title( + "Nodo" + ) + .render() +} diff --git a/pagetop-node/src/locales/en-US/homepage.ftl b/pagetop-node/src/locales/en-US/homepage.ftl new file mode 100644 index 00000000..191dc81f --- /dev/null +++ b/pagetop-node/src/locales/en-US/homepage.ftl @@ -0,0 +1,2 @@ +module_fullname = Node +module_description = Allows content to be submitted to the site and displayed on pages. diff --git a/pagetop-node/src/locales/es-ES/homepage.ftl b/pagetop-node/src/locales/es-ES/homepage.ftl new file mode 100644 index 00000000..b5e6677d --- /dev/null +++ b/pagetop-node/src/locales/es-ES/homepage.ftl @@ -0,0 +1,2 @@ +module_fullname = Nodo +module_description = Permite enviar contenidos al sitio y mostrarlos en páginas. diff --git a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs new file mode 100644 index 00000000..5180a785 --- /dev/null +++ b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs @@ -0,0 +1,90 @@ +use pagetop::db::migration::*; + +/// Stores information about all defined {node} types. +#[derive(Iden)] +enum NodeType { + Table, // Nombre de la tabla: node_type (Tipo de nodo). + Type, // The machine-readable name of this type + Name, // The human-readable name of this type + Description, // Descripción breve del tipo. + Help, // Help information shown to the user when creating a {node} of this type + HasTitle, // Boolean indicating whether this type uses the {node}.title field + TitleLabel, // The label displayed for the title field on the edit form + Custom, // A boolean indicating whether this type is defined by a module (FALSE) or by a user via Add content type (TRUE) + Locked, // A boolean indicating whether the administrator can change the machine name of this type + Disabled, // A boolean indicating whether the node type is disabled + OrigType, // The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0 +} + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220316_000001_create_table_node_type" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(NodeType::Table) + .if_not_exists() + .col(ColumnDef::new(NodeType::Type) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(NodeType::Name) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Description) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Help) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::HasTitle) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::TitleLabel) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Custom) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Locked) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Disabled) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::OrigType) + .string() + .not_null() + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(NodeType::Table) + .to_owned() + ) + .await + } +} diff --git a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs new file mode 100644 index 00000000..fe65fc2c --- /dev/null +++ b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs @@ -0,0 +1,110 @@ +use pagetop::db::migration::*; + +/// The base table for nodes. +#[derive(Iden)] +enum Node { + Table, // Nombre de la tabla: node (Nodo). + Nid, // The primary identifier for a node + Vid, // The current {node_revision}.vid version identifier + Type, // The {node_type}.type of this node + Language, // The {languages}.language of this node + Title, // The title of this node, always treated as non-markup plain text + Uid, // The {users}.uid that owns this node; initially, this is the user that created it + Status, // Boolean indicating whether the node is published (visible to non-administrators) + Created, // The Unix timestamp when the node was created + Changed, // The Unix timestamp when the node was most recently saved + Comment, // Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write) + Promote, // Boolean indicating whether the node should be displayed on the front page + Sticky, // Boolean indicating whether the node should be displayed at the top of lists in which it appears + Tnid, // The translation set id for this node, which equals the node id of the source post in each set + Translate, // A boolean indicating whether this translation page needs to be updated +} + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220316_000002_create_table_node" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Node::Table) + .if_not_exists() + .col(ColumnDef::new(Node::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Node::Vid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Type) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Language) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Title) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Uid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Status) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Created) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Changed) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Comment) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Promote) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Sticky) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Tnid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Translate) + .string() + .not_null() + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(Node::Table) + .to_owned() + ) + .await + } +} diff --git a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs new file mode 100644 index 00000000..a179240f --- /dev/null +++ b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs @@ -0,0 +1,70 @@ +use pagetop::db::migration::*; + +// Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes. +#[derive(Iden)] +enum NodeAccess { + Table, // Nombre de la tabla: node_access (Acceso a nodos). + Nid, // The {node}.nid this record affects + Gid, // The grant ID a user must possess in the specified realm to gain this row's privileges on the node + Realm, // The realm in which the user must possess the grant ID. Each node access node can define one or more realms + GrantView, // Boolean indicating whether a user with the realm/grant pair can view this node + GrantUpdate, // Boolean indicating whether a user with the realm/grant pair can edit this node + GrantDelete, // Boolean indicating whether a user with the realm/grant pair can delete this node +} + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220316_000003_create_table_node_access" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(NodeAccess::Table) + .if_not_exists() + .col(ColumnDef::new(NodeAccess::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(NodeAccess::Gid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::Realm) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantView) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantUpdate) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantDelete) + .string() + .not_null() + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(NodeAccess::Table) + .to_owned() + ) + .await + } +} diff --git a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs new file mode 100644 index 00000000..4dc4e1b6 --- /dev/null +++ b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs @@ -0,0 +1,90 @@ +use pagetop::db::migration::*; + +// Stores information about each saved version of a {node}. +#[derive(Iden)] +enum NodeRevision { + Table, // Nombre de la tabla: node_revisión (Versiones de nodos). + Nid, // The {node} this version belongs to + Vid, // The primary identifier for this version + Uid, // The {users}.uid that created this version + Title, // The title of this version + Log, // The log entry explaining the changes in this version + Timestamp, // A Unix timestamp indicating when this version was created + Status, // Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators) + Comment, // Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write) + Promote, // Boolean indicating whether the node (at the time of this revision) should be displayed on the front page + Sticky, // Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears +} + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220316_000004_create_table_node_revision" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(NodeRevision::Table) + .if_not_exists() + .col(ColumnDef::new(NodeRevision::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(NodeRevision::Vid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Uid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Title) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Log) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Timestamp) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Status) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Comment) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Promote) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Sticky) + .string() + .not_null() + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(NodeRevision::Table) + .to_owned() + ) + .await + } +} diff --git a/pagetop-node/src/migration/mod.rs b/pagetop-node/src/migration/mod.rs new file mode 100644 index 00000000..49f4e057 --- /dev/null +++ b/pagetop-node/src/migration/mod.rs @@ -0,0 +1,4 @@ +pub mod m20220316_000001_create_table_node_type; +pub mod m20220316_000002_create_table_node; +pub mod m20220316_000003_create_table_node_access; +pub mod m20220316_000004_create_table_node_revision; diff --git a/pagetop-user/Cargo.toml b/pagetop-user/Cargo.toml new file mode 100644 index 00000000..37352fe7 --- /dev/null +++ b/pagetop-user/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "pagetop-user" +version = "0.0.1" +edition = "2021" + +authors = [ + "Manuel Cillero " +] +description = """\ + Allows content to be submitted to the site and displayed on pages.\ +""" +homepage = "https://suitepro.cillero.es/projects/drust" +repository = "https://gitlab.com/manuelcillero/drust" + +[dependencies] +pagetop = { path = "../pagetop" } +serde = { version = "1.0", features = ["derive"] } + +[dependencies.sea-orm] +version = "0.6.0" +features = ["debug-print", "macros"] +default-features = false diff --git a/pagetop/src/base/module/user/entity/mod.rs b/pagetop-user/src/entity/mod.rs similarity index 100% rename from pagetop/src/base/module/user/entity/mod.rs rename to pagetop-user/src/entity/mod.rs diff --git a/pagetop/src/base/module/user/entity/user.rs b/pagetop-user/src/entity/user.rs similarity index 100% rename from pagetop/src/base/module/user/entity/user.rs rename to pagetop-user/src/entity/user.rs diff --git a/pagetop/src/base/module/user/mod.rs b/pagetop-user/src/lib.rs similarity index 80% rename from pagetop/src/base/module/user/mod.rs rename to pagetop-user/src/lib.rs index 362961eb..c76233e1 100644 --- a/pagetop/src/base/module/user/mod.rs +++ b/pagetop-user/src/lib.rs @@ -1,6 +1,6 @@ -use crate::prelude::*; +use pagetop::prelude::*; -localize!("src/base/module/user/locales"); +localize!("src/locales"); mod entity; mod migration; @@ -8,10 +8,6 @@ mod migration; pub struct UserModule; impl ModuleTrait for UserModule { - fn name(&self) -> &'static str { - "user" - } - fn fullname(&self) -> String { l("module_fullname") } @@ -20,8 +16,8 @@ impl ModuleTrait for UserModule { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { - cfg.route("/user/login", server::web::get().to(login)); + fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + cfg.route("/user/login", app::web::get().to(login)); } fn migrations(&self) -> Vec> { @@ -50,7 +46,7 @@ fn form_login() -> impl PageComponent { .add(form::Button::submit(l("login").as_str())) } -async fn login() -> server::Result { +async fn login() -> app::Result { Page::prepare() .with_title( "Identificación del usuario" diff --git a/pagetop/src/base/module/user/locales/en-US/homepage.ftl b/pagetop-user/src/locales/en-US/homepage.ftl similarity index 100% rename from pagetop/src/base/module/user/locales/en-US/homepage.ftl rename to pagetop-user/src/locales/en-US/homepage.ftl diff --git a/pagetop/src/base/module/user/locales/es-ES/homepage.ftl b/pagetop-user/src/locales/es-ES/homepage.ftl similarity index 100% rename from pagetop/src/base/module/user/locales/es-ES/homepage.ftl rename to pagetop-user/src/locales/es-ES/homepage.ftl diff --git a/pagetop/src/base/module/user/migration/m20220312_000001_create_table_user.rs b/pagetop-user/src/migration/m20220312_000001_create_table_user.rs similarity index 100% rename from pagetop/src/base/module/user/migration/m20220312_000001_create_table_user.rs rename to pagetop-user/src/migration/m20220312_000001_create_table_user.rs diff --git a/pagetop/src/base/module/user/migration/mod.rs b/pagetop-user/src/migration/mod.rs similarity index 100% rename from pagetop/src/base/module/user/migration/mod.rs rename to pagetop-user/src/migration/mod.rs diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index e6cbc75e..a9c7993c 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.1" +version = "0.0.2" edition = "2021" authors = [ diff --git a/pagetop/STARTER.Cargo.toml b/pagetop/STARTER.bin.Cargo.toml similarity index 88% rename from pagetop/STARTER.Cargo.toml rename to pagetop/STARTER.bin.Cargo.toml index 7cddd5fc..d05a17bf 100644 --- a/pagetop/STARTER.Cargo.toml +++ b/pagetop/STARTER.bin.Cargo.toml @@ -24,3 +24,8 @@ actix-web = "3.3.3" maud = { version = "0.23.0" } # Opcional. Si se requiere serialización de estructuras de datos. serde = { version = "1.0", features = ["derive"] } + +[dependencies.sea-orm] +version = "0.6.0" +features = ["debug-print", "macros"] +default-features = false diff --git a/pagetop/STARTER.lib.Cargo.toml b/pagetop/STARTER.lib.Cargo.toml new file mode 100644 index 00000000..97389750 --- /dev/null +++ b/pagetop/STARTER.lib.Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "app" +version = "0.1.0" +edition = "2021" + +# Ver más claves y sus definiciones en +# https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies.pagetop] +path = "../pagetop" +# Opcional. Por defecto se puede usar PageTop sin base de datos. +features = ["mysql"] +# features = ["postgres"] +# features = ["sqlite"] +# PageTop puede dar soporte a todas las bases de datos. +# features = ["mysql", "postgres", "sqlite"] +# Sólo cuando no se usen las características predeterminadas. +default-features = false + +[dependencies] +# Opcional. Sólo si se usa la macro html!. +maud = { version = "0.23.0" } +# Opcional. Si se requiere serialización de estructuras de datos. +serde = { version = "1.0", features = ["derive"] } + +[dependencies.sea-orm] +version = "0.6.0" +features = ["debug-print", "macros"] +default-features = false diff --git a/pagetop/src/core/all.rs b/pagetop/src/all.rs similarity index 83% rename from pagetop/src/core/all.rs rename to pagetop/src/all.rs index 20df22bd..a7134172 100644 --- a/pagetop/src/core/all.rs +++ b/pagetop/src/all.rs @@ -1,8 +1,7 @@ -use crate::{Lazy, run_now}; +use crate::{Lazy, run_now, app}; use crate::db::migration::*; -use crate::core::theme::ThemeTrait; -use crate::core::module::ModuleTrait; -use crate::core::server; +use crate::theme::ThemeTrait; +use crate::module::ModuleTrait; use std::sync::RwLock; @@ -16,7 +15,7 @@ pub static THEMES: Lazy>> = Lazy::new( || { RwLock::new(Vec::new()) } ); -pub fn themes(cfg: &mut server::web::ServiceConfig) { +pub fn themes(cfg: &mut app::web::ServiceConfig) { cfg.service(actix_web_static_files::ResourceFiles::new( "/theme", assets() @@ -35,7 +34,7 @@ pub static MODULES: Lazy>> = Lazy::new( || { RwLock::new(Vec::new()) } ); -pub fn modules(cfg: &mut server::web::ServiceConfig) { +pub fn modules(cfg: &mut app::web::ServiceConfig) { for m in MODULES.read().unwrap().iter() { m.configure_module(cfg); } @@ -54,6 +53,6 @@ pub fn run_migrations() { migrations } } - Migrator::up(&server::db::DBCONN, None) + Migrator::up(&app::db::DBCONN, None) }).unwrap(); } diff --git a/pagetop/src/core/server/app.rs b/pagetop/src/app/application.rs similarity index 73% rename from pagetop/src/core/server/app.rs rename to pagetop/src/app/application.rs index 74e1690d..12af039c 100644 --- a/pagetop/src/core/server/app.rs +++ b/pagetop/src/app/application.rs @@ -1,14 +1,13 @@ -use crate::{Lazy, base, trace}; +use crate::{Lazy, all, app, trace}; use crate::config::SETTINGS; -use crate::core::{Server, all, server}; -use crate::core::theme::register_theme; -use crate::core::module::register_module; +use crate::theme::*; +use crate::module::*; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; pub struct Application { - server: Server, + server: app::Server, } pub fn essence() { @@ -44,25 +43,19 @@ impl Application { } // Inicia registro de trazas y eventos. - Lazy::force(&server::tracing::TRACING); + Lazy::force(&app::tracing::TRACING); // Valida el identificador de idioma. - Lazy::force(&server::locale::LANGID); + Lazy::force(&app::locale::LANGID); // Conecta con la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - Lazy::force(&server::db::DBCONN); + Lazy::force(&app::db::DBCONN); // Registra los temas predefinidos. - register_theme(&base::theme::aliner::AlinerTheme); - register_theme(&base::theme::minimal::MinimalTheme); - register_theme(&base::theme::bootsier::BootsierTheme); - - // Registra los módulos predeterminados. - register_module(&base::module::admin::AdminModule); - // Registra los módulos que requieren base de datos. - #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - register_module(&base::module::user::UserModule); + register_theme(&aliner::AlinerTheme); + register_theme(&minimal::MinimalTheme); + register_theme(&bootsier::BootsierTheme); // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); @@ -70,15 +63,15 @@ impl Application { // Registra el módulo para la página de inicio de PageTop. // Al ser el último, puede sobrecargarse con la función de inicio. - register_module(&base::module::homepage::HomepageModule); + register_module(&homepage::HomepageModule); // Comprueba actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] all::run_migrations(); // Prepara el servidor web. - let server = server::HttpServer::new(move || { - server::App::new() + let server = app::HttpServer::new(move || { + app::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(NormalizePath::new(TrailingSlash::Trim)) .configure(&all::themes) @@ -93,7 +86,7 @@ impl Application { Ok(Self { server }) } - pub fn run(self) -> Result { + pub fn run(self) -> Result { Ok(self.server) } } diff --git a/pagetop/src/core/server/db.rs b/pagetop/src/app/db.rs similarity index 100% rename from pagetop/src/core/server/db.rs rename to pagetop/src/app/db.rs diff --git a/pagetop/src/core/server/figfonts/slant.flf b/pagetop/src/app/figfonts/slant.flf similarity index 100% rename from pagetop/src/core/server/figfonts/slant.flf rename to pagetop/src/app/figfonts/slant.flf diff --git a/pagetop/src/core/server/figfonts/small.flf b/pagetop/src/app/figfonts/small.flf similarity index 100% rename from pagetop/src/core/server/figfonts/small.flf rename to pagetop/src/app/figfonts/small.flf diff --git a/pagetop/src/core/server/figfonts/speed.flf b/pagetop/src/app/figfonts/speed.flf similarity index 100% rename from pagetop/src/core/server/figfonts/speed.flf rename to pagetop/src/app/figfonts/speed.flf diff --git a/pagetop/src/core/server/figfonts/starwars.flf b/pagetop/src/app/figfonts/starwars.flf similarity index 100% rename from pagetop/src/core/server/figfonts/starwars.flf rename to pagetop/src/app/figfonts/starwars.flf diff --git a/pagetop/src/core/server/locale.rs b/pagetop/src/app/locale.rs similarity index 100% rename from pagetop/src/core/server/locale.rs rename to pagetop/src/app/locale.rs diff --git a/pagetop/src/core/server/mod.rs b/pagetop/src/app/mod.rs similarity index 81% rename from pagetop/src/core/server/mod.rs rename to pagetop/src/app/mod.rs index 394886b4..b3f7cd6a 100644 --- a/pagetop/src/core/server/mod.rs +++ b/pagetop/src/app/mod.rs @@ -1,6 +1,7 @@ pub use actix_web::{ App, HttpRequest, HttpResponse, HttpServer, Responder, Result, http, web }; +use actix_web::dev::Server; mod tracing; @@ -9,4 +10,4 @@ pub mod locale; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; -pub mod app; +pub mod application; diff --git a/pagetop/src/core/server/tracing.rs b/pagetop/src/app/tracing.rs similarity index 100% rename from pagetop/src/core/server/tracing.rs rename to pagetop/src/app/tracing.rs diff --git a/pagetop/src/base/mod.rs b/pagetop/src/base/mod.rs deleted file mode 100644 index f40d2d0e..00000000 --- a/pagetop/src/base/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Temas, Módulos y Componentes base. - -pub mod theme; -pub mod module; -pub mod component; diff --git a/pagetop/src/base/module/admin/mod.rs b/pagetop/src/base/module/admin/mod.rs deleted file mode 100644 index e9b58703..00000000 --- a/pagetop/src/base/module/admin/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::prelude::*; - -localize!("src/base/module/admin/locales"); - -mod summary; - -pub struct AdminModule; - -impl ModuleTrait for AdminModule { - fn name(&self) -> &'static str { - "admin" - } - - fn fullname(&self) -> String { - l("module_fullname") - } - - fn description(&self) -> Option { - Some(l("module_description")) - } - - fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { - cfg.service( - server::web::scope("/admin") - .route("", server::web::get().to(summary::summary)) - ); - } -} diff --git a/pagetop/src/base/module/mod.rs b/pagetop/src/base/module/mod.rs deleted file mode 100644 index ab1169b4..00000000 --- a/pagetop/src/base/module/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod admin; -pub mod homepage; - -#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub mod user; diff --git a/pagetop/src/base/theme/mod.rs b/pagetop/src/base/theme/mod.rs deleted file mode 100644 index 8794ed17..00000000 --- a/pagetop/src/base/theme/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod aliner; -pub mod minimal; -pub mod bootsier; diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/component/block.rs similarity index 100% rename from pagetop/src/base/component/block.rs rename to pagetop/src/component/block.rs diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/component/chunck.rs similarity index 100% rename from pagetop/src/base/component/chunck.rs rename to pagetop/src/component/chunck.rs diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/component/container.rs similarity index 100% rename from pagetop/src/base/component/container.rs rename to pagetop/src/component/container.rs diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/component/form/button.rs similarity index 100% rename from pagetop/src/base/component/form/button.rs rename to pagetop/src/component/form/button.rs diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/component/form/date.rs similarity index 100% rename from pagetop/src/base/component/form/date.rs rename to pagetop/src/component/form/date.rs diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/component/form/form.rs similarity index 100% rename from pagetop/src/base/component/form/form.rs rename to pagetop/src/component/form/form.rs diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/component/form/hidden.rs similarity index 100% rename from pagetop/src/base/component/form/hidden.rs rename to pagetop/src/component/form/hidden.rs diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/component/form/input.rs similarity index 100% rename from pagetop/src/base/component/form/input.rs rename to pagetop/src/component/form/input.rs diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/component/form/mod.rs similarity index 100% rename from pagetop/src/base/component/form/mod.rs rename to pagetop/src/component/form/mod.rs diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/component/menu.rs similarity index 100% rename from pagetop/src/base/component/menu.rs rename to pagetop/src/component/menu.rs diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/component/mod.rs similarity index 100% rename from pagetop/src/base/component/mod.rs rename to pagetop/src/component/mod.rs diff --git a/pagetop/src/core/mod.rs b/pagetop/src/core/mod.rs deleted file mode 100644 index 8db86b83..00000000 --- a/pagetop/src/core/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub use actix_web::dev::Server; - -mod all; - -pub mod html; -pub mod theme; -pub mod module; -pub mod response; -pub mod server; diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module/mod.rs deleted file mode 100644 index 2a42352a..00000000 --- a/pagetop/src/core/module/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::core::all; - -mod definition; -pub use definition::ModuleTrait; - -pub fn register_module(m: &'static (dyn ModuleTrait + 'static)) { - all::MODULES.write().unwrap().push(m); -} - -pub fn find_module(name: &str) -> Option<&'static (dyn ModuleTrait + 'static)> { - let modules = all::MODULES.write().unwrap(); - match modules.iter().find(|t| t.name() == name) { - Some(module) => Some(*module), - _ => None, - } -} diff --git a/pagetop/src/core/html.rs b/pagetop/src/html.rs similarity index 100% rename from pagetop/src/core/html.rs rename to pagetop/src/html.rs diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index daf0577d..1ecb2028 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -8,6 +8,8 @@ pub use futures::executor::block_on as run_now; // APIs públicas. // ----------------------------------------------------------------------------- +mod all; // Variables globales privadas. + pub mod config; // Gestión de la configuración. pub mod trace; // Registro de trazas y eventos de la aplicación. pub mod locale; // Localización. @@ -15,8 +17,14 @@ pub mod locale; // Localización. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a la base de datos. -pub mod core; // Servidor web y APIs para Temas, Módulos y Respuestas web. -pub mod base; // Temas, Módulos y Componentes base. +pub mod html; // Publicación de código HTML desde el código. +pub mod theme; // API para crear temas y temas predeterminados. +pub mod module; // API para crear módulos con nuevas funcionalidades. +pub mod response; // Tipos de respuestas web. +pub mod app; // Aplicación y servidor web. + +pub mod component; // Componentes base. + pub mod util; // Macros y funciones útiles. pub mod prelude; // Re-exporta recursos comunes. diff --git a/pagetop/src/locale.rs b/pagetop/src/locale.rs index a5a136c2..93e9e7e8 100644 --- a/pagetop/src/locale.rs +++ b/pagetop/src/locale.rs @@ -7,7 +7,7 @@ pub use fluent_templates::fluent_bundle::FluentValue; macro_rules! localize { ( $dir_locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; - use $crate::core::server::locale::LANGID; + use $crate::app::locale::LANGID; static_locale! { static LOCALES = { @@ -37,8 +37,8 @@ macro_rules! localize { fn e( key: &str, args: &std::collections::HashMap - ) -> $crate::core::html::PreEscaped { - $crate::core::html::PreEscaped( + ) -> $crate::html::PreEscaped { + $crate::html::PreEscaped( LOCALES.lookup_with_args(&LANGID, key, args) ) } diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/module/definition.rs similarity index 56% rename from pagetop/src/core/module/definition.rs rename to pagetop/src/module/definition.rs index c50cace3..ccebe607 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -1,20 +1,31 @@ -use crate::core::server; - #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; +use crate::app; + +use std::any::type_name; /// Los módulos deben implementar este *trait*. pub trait ModuleTrait: Send + Sync { - fn name(&self) -> &'static str; + fn name(&self) -> &'static str { + let name = type_name::(); + match name.rfind("::") { + Some(position) => &name[(position + 2)..], + None => name + } + } fn fullname(&self) -> String; + fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } + fn description(&self) -> Option { None } #[allow(unused_variables)] - fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { + fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { } #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] diff --git a/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl b/pagetop/src/module/homepage/locales/en-US/homepage.ftl similarity index 100% rename from pagetop/src/base/module/homepage/locales/en-US/homepage.ftl rename to pagetop/src/module/homepage/locales/en-US/homepage.ftl diff --git a/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl b/pagetop/src/module/homepage/locales/es-ES/homepage.ftl similarity index 100% rename from pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl rename to pagetop/src/module/homepage/locales/es-ES/homepage.ftl diff --git a/pagetop/src/base/module/homepage/mod.rs b/pagetop/src/module/homepage/mod.rs similarity index 88% rename from pagetop/src/base/module/homepage/mod.rs rename to pagetop/src/module/homepage/mod.rs index 6b3b9741..c74480b3 100644 --- a/pagetop/src/base/module/homepage/mod.rs +++ b/pagetop/src/module/homepage/mod.rs @@ -1,14 +1,10 @@ use crate::prelude::*; -localize!("src/base/module/homepage/locales"); +localize!("src/module/homepage/locales"); pub struct HomepageModule; impl ModuleTrait for HomepageModule { - fn name(&self) -> &'static str { - "homepage" - } - fn fullname(&self) -> String { l("module_fullname") } @@ -17,12 +13,12 @@ impl ModuleTrait for HomepageModule { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut server::web::ServiceConfig) { - cfg.route("/", server::web::get().to(home)); + fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + cfg.route("/", app::web::get().to(home)); } } -async fn home() -> server::Result { +async fn home() -> app::Result { Page::prepare() .with_title( l("page_title").as_str() diff --git a/pagetop/src/module/mod.rs b/pagetop/src/module/mod.rs new file mode 100644 index 00000000..cb71dfd2 --- /dev/null +++ b/pagetop/src/module/mod.rs @@ -0,0 +1,17 @@ +use crate::{all, trace}; + +mod definition; +pub use definition::ModuleTrait; + +pub mod homepage; + +pub fn register_module(m: &'static dyn ModuleTrait) { + let mut modules = all::MODULES.write().unwrap(); + match modules.iter().find(|t| t.name() == m.name()) { + None => { + trace::info!("{}", m.name()); + modules.push(m); + }, + Some(_) => {}, + } +} diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 18d160ce..1bfc1817 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -8,13 +8,14 @@ pub use crate::localize; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::{db, boxed_migration}; -pub use crate::core::html::*; -pub use crate::core::theme::*; -pub use crate::core::module::*; -pub use crate::core::response::page::*; -pub use crate::core::server; -pub use crate::core::server::app::{Application, essence}; +pub use crate::html::*; +pub use crate::theme::*; +pub use crate::module::*; +pub use crate::response::page::*; -pub use crate::base::component::*; +pub use crate::app; +pub use crate::app::application::{Application, essence}; + +pub use crate::component::*; pub use crate::util; diff --git a/pagetop/src/core/response/mod.rs b/pagetop/src/response/mod.rs similarity index 100% rename from pagetop/src/core/response/mod.rs rename to pagetop/src/response/mod.rs diff --git a/pagetop/src/core/response/page/assets.rs b/pagetop/src/response/page/assets.rs similarity index 98% rename from pagetop/src/core/response/page/assets.rs rename to pagetop/src/response/page/assets.rs index 2bd96fc2..9c30d981 100644 --- a/pagetop/src/core/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -1,8 +1,7 @@ -use crate::{Lazy, base}; +use crate::{Lazy, all}; use crate::config::SETTINGS; -use crate::core::all; -use crate::core::html::{Markup, PreEscaped, html}; -use crate::core::theme::*; +use crate::html::{Markup, PreEscaped, html}; +use crate::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { for t in all::THEMES.read().unwrap().iter() { @@ -10,7 +9,7 @@ static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { return *t; } } - &base::theme::bootsier::BootsierTheme + &bootsier::BootsierTheme }); // ----------------------------------------------------------------------------- diff --git a/pagetop/src/core/response/page/component.rs b/pagetop/src/response/page/component.rs similarity index 90% rename from pagetop/src/core/response/page/component.rs rename to pagetop/src/response/page/component.rs index 78925468..26151cab 100644 --- a/pagetop/src/core/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -1,5 +1,5 @@ -use crate::core::html::{Markup, html}; -use crate::core::response::page::PageAssets; +use crate::html::{Markup, html}; +use crate::response::page::PageAssets; use downcast_rs::{Downcast, impl_downcast}; diff --git a/pagetop/src/core/response/page/container.rs b/pagetop/src/response/page/container.rs similarity index 86% rename from pagetop/src/core/response/page/container.rs rename to pagetop/src/response/page/container.rs index 4a577b2d..72287560 100644 --- a/pagetop/src/core/response/page/container.rs +++ b/pagetop/src/response/page/container.rs @@ -1,5 +1,5 @@ -use crate::core::html::{Markup, html}; -use crate::core::response::page::{PageAssets, PageComponent, render_component}; +use crate::html::{Markup, html}; +use crate::response::page::{PageAssets, PageComponent, render_component}; use std::sync::Arc; diff --git a/pagetop/src/core/response/page/mod.rs b/pagetop/src/response/page/mod.rs similarity index 100% rename from pagetop/src/core/response/page/mod.rs rename to pagetop/src/response/page/mod.rs diff --git a/pagetop/src/core/response/page/page.rs b/pagetop/src/response/page/page.rs similarity index 96% rename from pagetop/src/core/response/page/page.rs rename to pagetop/src/response/page/page.rs index d47a33f1..58541d22 100644 --- a/pagetop/src/core/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,8 +1,7 @@ -use crate::{Lazy, trace, util}; +use crate::{Lazy, app, trace, util}; use crate::config::SETTINGS; -use crate::core::html::{DOCTYPE, Markup, html}; -use crate::core::response::page::{PageAssets, PageComponent, PageContainer}; -use crate::core::server; +use crate::html::{DOCTYPE, Markup, html}; +use crate::response::page::{PageAssets, PageComponent, PageContainer}; use std::borrow::Cow; use std::sync::RwLock; @@ -164,7 +163,7 @@ impl<'a> Page<'a> { // Page RENDER. - pub fn render(&mut self) -> server::Result { + pub fn render(&mut self) -> app::Result { // Acciones del tema antes de renderizar la página. self.assets.theme().before_render_page(self); diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/theme/aliner/mod.rs similarity index 90% rename from pagetop/src/base/theme/aliner/mod.rs rename to pagetop/src/theme/aliner/mod.rs index 18df448f..676eb25d 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/theme/aliner/mod.rs @@ -13,7 +13,7 @@ impl ThemeTrait for AlinerTheme { "Aliner".to_owned() } - fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { cfg.service(actix_web_static_files::ResourceFiles::new( "/aliner", assets() diff --git a/pagetop/src/base/theme/bootsier/locales/en-US/bootsier.ftl b/pagetop/src/theme/bootsier/locales/en-US/bootsier.ftl similarity index 100% rename from pagetop/src/base/theme/bootsier/locales/en-US/bootsier.ftl rename to pagetop/src/theme/bootsier/locales/en-US/bootsier.ftl diff --git a/pagetop/src/base/theme/bootsier/locales/es-ES/bootsier.ftl b/pagetop/src/theme/bootsier/locales/es-ES/bootsier.ftl similarity index 100% rename from pagetop/src/base/theme/bootsier/locales/es-ES/bootsier.ftl rename to pagetop/src/theme/bootsier/locales/es-ES/bootsier.ftl diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/theme/bootsier/mod.rs similarity index 88% rename from pagetop/src/base/theme/bootsier/mod.rs rename to pagetop/src/theme/bootsier/mod.rs index 3c4176f0..6fba1615 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/theme/bootsier/mod.rs @@ -2,7 +2,7 @@ use crate::prelude::*; include!(concat!(env!("OUT_DIR"), "/bootsier.rs")); -localize!("src/base/theme/bootsier/locales"); +localize!("src/theme/bootsier/locales"); pub struct BootsierTheme; @@ -15,7 +15,7 @@ impl ThemeTrait for BootsierTheme { "Bootsier".to_owned() } - fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { cfg.service(actix_web_static_files::ResourceFiles::new( "/bootsier", assets() @@ -43,16 +43,16 @@ impl ThemeTrait for BootsierTheme { .add_jquery(); } - fn render_error_page(&self, mut s: server::http::StatusCode) -> server::Result { + fn render_error_page(&self, mut s: app::http::StatusCode) -> app::Result { let mut description = "e500-description"; let mut message = "e500-description"; match s { - server::http::StatusCode::NOT_FOUND => { + app::http::StatusCode::NOT_FOUND => { description = "e404-description"; message = "e404-message"; }, _ => { - s = server::http::StatusCode::INTERNAL_SERVER_ERROR; + s = app::http::StatusCode::INTERNAL_SERVER_ERROR; } } Page::prepare() diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/theme/definition.rs similarity index 89% rename from pagetop/src/core/theme/definition.rs rename to pagetop/src/theme/definition.rs index eb67ec10..38ad1bfd 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,8 +1,8 @@ use crate::config::SETTINGS; -use crate::core::html::{Markup, html}; -use crate::core::response::page::{Page, PageAssets, PageComponent}; -use crate::core::server; -use crate::base::component::Chunck; +use crate::html::{Markup, html}; +use crate::response::page::{Page, PageAssets, PageComponent}; +use crate::app; +use crate::component::Chunck; /// Los temas deben implementar este "trait". pub trait ThemeTrait: Send + Sync { @@ -15,7 +15,7 @@ pub trait ThemeTrait: Send + Sync { } #[allow(unused_variables)] - fn configure_theme(&self, cfg: &mut server::web::ServiceConfig) { + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { } #[allow(unused_variables)] @@ -93,7 +93,7 @@ pub trait ThemeTrait: Send + Sync { */ } - fn render_error_page(&self, s: server::http::StatusCode) -> server::Result { + fn render_error_page(&self, s: app::http::StatusCode) -> app::Result { Page::prepare() .with_title(format!("Error {}", s.as_str()).as_str()) .add_to("content", Chunck::markup(html! { diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/theme/minimal/mod.rs similarity index 100% rename from pagetop/src/base/theme/minimal/mod.rs rename to pagetop/src/theme/minimal/mod.rs diff --git a/pagetop/src/core/theme/mod.rs b/pagetop/src/theme/mod.rs similarity index 58% rename from pagetop/src/core/theme/mod.rs rename to pagetop/src/theme/mod.rs index e83f4307..9b045708 100644 --- a/pagetop/src/core/theme/mod.rs +++ b/pagetop/src/theme/mod.rs @@ -1,13 +1,17 @@ -use crate::core::all; +use crate::all; mod definition; pub use definition::ThemeTrait; -pub fn register_theme(t: &'static (dyn ThemeTrait + 'static)) { +pub mod aliner; +pub mod minimal; +pub mod bootsier; + +pub fn register_theme(t: &'static dyn ThemeTrait) { all::THEMES.write().unwrap().push(t); } -pub fn find_theme(name: &str) -> Option<&'static (dyn ThemeTrait + 'static)> { +pub fn find_theme(name: &str) -> Option<&'static dyn ThemeTrait> { let themes = all::THEMES.write().unwrap(); match themes.iter().find(|t| t.name() == name) { Some(theme) => Some(*theme), From 3ee5859eae895ece4487d5c9db7cf809a3e2bb9b Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 19 Mar 2022 22:52:05 +0100 Subject: [PATCH 05/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- pagetop/src/app/application.rs | 22 ++--- pagetop/src/{ => base}/component/block.rs | 0 pagetop/src/{ => base}/component/chunck.rs | 0 pagetop/src/{ => base}/component/container.rs | 0 .../src/{ => base}/component/form/button.rs | 0 pagetop/src/{ => base}/component/form/date.rs | 0 pagetop/src/{ => base}/component/form/form.rs | 0 .../src/{ => base}/component/form/hidden.rs | 0 .../src/{ => base}/component/form/input.rs | 0 pagetop/src/{ => base}/component/form/mod.rs | 0 pagetop/src/{ => base}/component/menu.rs | 0 pagetop/src/{ => base}/component/mod.rs | 0 pagetop/src/base/mod.rs | 3 + .../homepage/locales/en-US/homepage.ftl | 0 .../homepage/locales/es-ES/homepage.ftl | 0 pagetop/src/{ => base}/module/homepage/mod.rs | 2 +- pagetop/src/base/module/mod.rs | 1 + pagetop/src/{ => base}/theme/aliner/mod.rs | 0 .../theme/bootsier/locales/en-US/bootsier.ftl | 0 .../theme/bootsier/locales/es-ES/bootsier.ftl | 0 pagetop/src/{ => base}/theme/bootsier/mod.rs | 2 +- pagetop/src/{ => base}/theme/minimal/mod.rs | 0 pagetop/src/base/theme/mod.rs | 3 + pagetop/src/{all.rs => global.rs} | 86 +++++++++++++------ pagetop/src/lib.rs | 9 +- pagetop/src/module/definition.rs | 3 +- pagetop/src/module/mod.rs | 15 +--- pagetop/src/prelude.rs | 2 +- pagetop/src/response/page/assets.rs | 14 +-- pagetop/src/theme/definition.rs | 4 +- pagetop/src/theme/mod.rs | 19 +--- 32 files changed, 94 insertions(+), 93 deletions(-) rename pagetop/src/{ => base}/component/block.rs (100%) rename pagetop/src/{ => base}/component/chunck.rs (100%) rename pagetop/src/{ => base}/component/container.rs (100%) rename pagetop/src/{ => base}/component/form/button.rs (100%) rename pagetop/src/{ => base}/component/form/date.rs (100%) rename pagetop/src/{ => base}/component/form/form.rs (100%) rename pagetop/src/{ => base}/component/form/hidden.rs (100%) rename pagetop/src/{ => base}/component/form/input.rs (100%) rename pagetop/src/{ => base}/component/form/mod.rs (100%) rename pagetop/src/{ => base}/component/menu.rs (100%) rename pagetop/src/{ => base}/component/mod.rs (100%) create mode 100644 pagetop/src/base/mod.rs rename pagetop/src/{ => base}/module/homepage/locales/en-US/homepage.ftl (100%) rename pagetop/src/{ => base}/module/homepage/locales/es-ES/homepage.ftl (100%) rename pagetop/src/{ => base}/module/homepage/mod.rs (97%) create mode 100644 pagetop/src/base/module/mod.rs rename pagetop/src/{ => base}/theme/aliner/mod.rs (100%) rename pagetop/src/{ => base}/theme/bootsier/locales/en-US/bootsier.ftl (100%) rename pagetop/src/{ => base}/theme/bootsier/locales/es-ES/bootsier.ftl (100%) rename pagetop/src/{ => base}/theme/bootsier/mod.rs (98%) rename pagetop/src/{ => base}/theme/minimal/mod.rs (100%) create mode 100644 pagetop/src/base/theme/mod.rs rename pagetop/src/{all.rs => global.rs} (57%) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index a9c7993c..db491819 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.2" +version = "0.0.3" edition = "2021" authors = [ diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 12af039c..274203e6 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -1,7 +1,6 @@ -use crate::{Lazy, all, app, trace}; +use crate::{Lazy, app, base, global, trace}; use crate::config::SETTINGS; -use crate::theme::*; -use crate::module::*; +use crate::module::register_module; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; @@ -52,30 +51,25 @@ impl Application { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] Lazy::force(&app::db::DBCONN); - // Registra los temas predefinidos. - register_theme(&aliner::AlinerTheme); - register_theme(&minimal::MinimalTheme); - register_theme(&bootsier::BootsierTheme); - // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); let _ = &bootstrap(); - // Registra el módulo para la página de inicio de PageTop. - // Al ser el último, puede sobrecargarse con la función de inicio. - register_module(&homepage::HomepageModule); + // Registra el módulo para una página de presentación de PageTop. + // Normalmente se sobrecargará en la función de inicio. + register_module(&base::module::homepage::HomepageModule); // Comprueba actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - all::run_migrations(); + global::run_migrations(); // Prepara el servidor web. let server = app::HttpServer::new(move || { app::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(NormalizePath::new(TrailingSlash::Trim)) - .configure(&all::themes) - .configure(&all::modules) + .configure(&global::themes) + .configure(&global::modules) }) .bind(format!("{}:{}", &SETTINGS.webserver.bind_address, diff --git a/pagetop/src/component/block.rs b/pagetop/src/base/component/block.rs similarity index 100% rename from pagetop/src/component/block.rs rename to pagetop/src/base/component/block.rs diff --git a/pagetop/src/component/chunck.rs b/pagetop/src/base/component/chunck.rs similarity index 100% rename from pagetop/src/component/chunck.rs rename to pagetop/src/base/component/chunck.rs diff --git a/pagetop/src/component/container.rs b/pagetop/src/base/component/container.rs similarity index 100% rename from pagetop/src/component/container.rs rename to pagetop/src/base/component/container.rs diff --git a/pagetop/src/component/form/button.rs b/pagetop/src/base/component/form/button.rs similarity index 100% rename from pagetop/src/component/form/button.rs rename to pagetop/src/base/component/form/button.rs diff --git a/pagetop/src/component/form/date.rs b/pagetop/src/base/component/form/date.rs similarity index 100% rename from pagetop/src/component/form/date.rs rename to pagetop/src/base/component/form/date.rs diff --git a/pagetop/src/component/form/form.rs b/pagetop/src/base/component/form/form.rs similarity index 100% rename from pagetop/src/component/form/form.rs rename to pagetop/src/base/component/form/form.rs diff --git a/pagetop/src/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs similarity index 100% rename from pagetop/src/component/form/hidden.rs rename to pagetop/src/base/component/form/hidden.rs diff --git a/pagetop/src/component/form/input.rs b/pagetop/src/base/component/form/input.rs similarity index 100% rename from pagetop/src/component/form/input.rs rename to pagetop/src/base/component/form/input.rs diff --git a/pagetop/src/component/form/mod.rs b/pagetop/src/base/component/form/mod.rs similarity index 100% rename from pagetop/src/component/form/mod.rs rename to pagetop/src/base/component/form/mod.rs diff --git a/pagetop/src/component/menu.rs b/pagetop/src/base/component/menu.rs similarity index 100% rename from pagetop/src/component/menu.rs rename to pagetop/src/base/component/menu.rs diff --git a/pagetop/src/component/mod.rs b/pagetop/src/base/component/mod.rs similarity index 100% rename from pagetop/src/component/mod.rs rename to pagetop/src/base/component/mod.rs diff --git a/pagetop/src/base/mod.rs b/pagetop/src/base/mod.rs new file mode 100644 index 00000000..6a8ebdf7 --- /dev/null +++ b/pagetop/src/base/mod.rs @@ -0,0 +1,3 @@ +pub mod component; +pub mod module; +pub mod theme; \ No newline at end of file diff --git a/pagetop/src/module/homepage/locales/en-US/homepage.ftl b/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl similarity index 100% rename from pagetop/src/module/homepage/locales/en-US/homepage.ftl rename to pagetop/src/base/module/homepage/locales/en-US/homepage.ftl diff --git a/pagetop/src/module/homepage/locales/es-ES/homepage.ftl b/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl similarity index 100% rename from pagetop/src/module/homepage/locales/es-ES/homepage.ftl rename to pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl diff --git a/pagetop/src/module/homepage/mod.rs b/pagetop/src/base/module/homepage/mod.rs similarity index 97% rename from pagetop/src/module/homepage/mod.rs rename to pagetop/src/base/module/homepage/mod.rs index c74480b3..bd364534 100644 --- a/pagetop/src/module/homepage/mod.rs +++ b/pagetop/src/base/module/homepage/mod.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -localize!("src/module/homepage/locales"); +localize!("src/base/module/homepage/locales"); pub struct HomepageModule; diff --git a/pagetop/src/base/module/mod.rs b/pagetop/src/base/module/mod.rs new file mode 100644 index 00000000..070e5b82 --- /dev/null +++ b/pagetop/src/base/module/mod.rs @@ -0,0 +1 @@ +pub mod homepage; diff --git a/pagetop/src/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs similarity index 100% rename from pagetop/src/theme/aliner/mod.rs rename to pagetop/src/base/theme/aliner/mod.rs diff --git a/pagetop/src/theme/bootsier/locales/en-US/bootsier.ftl b/pagetop/src/base/theme/bootsier/locales/en-US/bootsier.ftl similarity index 100% rename from pagetop/src/theme/bootsier/locales/en-US/bootsier.ftl rename to pagetop/src/base/theme/bootsier/locales/en-US/bootsier.ftl diff --git a/pagetop/src/theme/bootsier/locales/es-ES/bootsier.ftl b/pagetop/src/base/theme/bootsier/locales/es-ES/bootsier.ftl similarity index 100% rename from pagetop/src/theme/bootsier/locales/es-ES/bootsier.ftl rename to pagetop/src/base/theme/bootsier/locales/es-ES/bootsier.ftl diff --git a/pagetop/src/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs similarity index 98% rename from pagetop/src/theme/bootsier/mod.rs rename to pagetop/src/base/theme/bootsier/mod.rs index 6fba1615..132dce32 100644 --- a/pagetop/src/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -2,7 +2,7 @@ use crate::prelude::*; include!(concat!(env!("OUT_DIR"), "/bootsier.rs")); -localize!("src/theme/bootsier/locales"); +localize!("src/base/theme/bootsier/locales"); pub struct BootsierTheme; diff --git a/pagetop/src/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs similarity index 100% rename from pagetop/src/theme/minimal/mod.rs rename to pagetop/src/base/theme/minimal/mod.rs diff --git a/pagetop/src/base/theme/mod.rs b/pagetop/src/base/theme/mod.rs new file mode 100644 index 00000000..baccfbd9 --- /dev/null +++ b/pagetop/src/base/theme/mod.rs @@ -0,0 +1,3 @@ +pub mod aliner; +pub mod bootsier; +pub mod minimal; diff --git a/pagetop/src/all.rs b/pagetop/src/global.rs similarity index 57% rename from pagetop/src/all.rs rename to pagetop/src/global.rs index a7134172..34280cf4 100644 --- a/pagetop/src/all.rs +++ b/pagetop/src/global.rs @@ -1,31 +1,11 @@ -use crate::{Lazy, run_now, app}; +use crate::{Lazy, app, base, run_now, trace}; +use crate::config::SETTINGS; use crate::db::migration::*; -use crate::theme::ThemeTrait; -use crate::module::ModuleTrait; +use crate::module::*; +use crate::theme::*; use std::sync::RwLock; -include!(concat!(env!("OUT_DIR"), "/theme.rs")); - -// ----------------------------------------------------------------------------- -// Temas registrados y tema predeterminado. -// ----------------------------------------------------------------------------- - -pub static THEMES: Lazy>> = Lazy::new( - || { RwLock::new(Vec::new()) } -); - -pub fn themes(cfg: &mut app::web::ServiceConfig) { - cfg.service(actix_web_static_files::ResourceFiles::new( - "/theme", - assets() - )); - - for t in THEMES.read().unwrap().iter() { - t.configure_theme(cfg); - } -} - // ----------------------------------------------------------------------------- // Módulos registrados. // ----------------------------------------------------------------------------- @@ -34,6 +14,17 @@ pub static MODULES: Lazy>> = Lazy::new( || { RwLock::new(Vec::new()) } ); +pub fn register_module(m: &'static dyn ModuleTrait) { + let mut modules = MODULES.write().unwrap(); + match modules.iter().find(|t| t.name() == m.name()) { + None => { + trace::info!("{}", m.name()); + modules.push(m); + }, + Some(_) => {}, + } +} + pub fn modules(cfg: &mut app::web::ServiceConfig) { for m in MODULES.read().unwrap().iter() { m.configure_module(cfg); @@ -56,3 +47,50 @@ pub fn run_migrations() { Migrator::up(&app::db::DBCONN, None) }).unwrap(); } + +// ----------------------------------------------------------------------------- +// Temas registrados y tema predeterminado. +// ----------------------------------------------------------------------------- + +include!(concat!(env!("OUT_DIR"), "/theme.rs")); + +pub static THEMES: Lazy>> = Lazy::new(|| { + RwLock::new(vec![ + &base::theme::aliner::AlinerTheme, + &base::theme::minimal::MinimalTheme, + &base::theme::bootsier::BootsierTheme, + ]) +}); + +pub static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { + for t in THEMES.read().unwrap().iter() { + if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() { + return *t; + } + } + &base::theme::bootsier::BootsierTheme +}); + +pub fn register_theme(t: &'static dyn ThemeTrait) { + THEMES.write().unwrap().push(t); +} + +pub fn theme_by_name(name: &str) -> Option<&'static dyn ThemeTrait> { + let themes = crate::global::THEMES.write().unwrap(); + match themes.iter().find(|t| t.name() == name) { + Some(theme) => Some(*theme), + _ => None, + } +} + +pub fn themes(cfg: &mut app::web::ServiceConfig) { + cfg.service(actix_web_static_files::ResourceFiles::new( + "/theme", + assets() + )); + + for t in THEMES.read().unwrap().iter() { + t.configure_theme(cfg); + } +} + diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 1ecb2028..3efe21aa 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -8,7 +8,7 @@ pub use futures::executor::block_on as run_now; // APIs públicas. // ----------------------------------------------------------------------------- -mod all; // Variables globales privadas. +mod global; // Ref. privadas globales a todos los temas y módulos. pub mod config; // Gestión de la configuración. pub mod trace; // Registro de trazas y eventos de la aplicación. @@ -17,14 +17,13 @@ pub mod locale; // Localización. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a la base de datos. -pub mod html; // Publicación de código HTML desde el código. -pub mod theme; // API para crear temas y temas predeterminados. +pub mod html; // Publicación de HTML desde el código. pub mod module; // API para crear módulos con nuevas funcionalidades. +pub mod theme; // API para crear temas y temas predeterminados. pub mod response; // Tipos de respuestas web. pub mod app; // Aplicación y servidor web. -pub mod component; // Componentes base. - +pub mod base; // Componentes, Módulos y Temas base. pub mod util; // Macros y funciones útiles. pub mod prelude; // Re-exporta recursos comunes. diff --git a/pagetop/src/module/definition.rs b/pagetop/src/module/definition.rs index ccebe607..9424fbd8 100644 --- a/pagetop/src/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -1,6 +1,7 @@ +use crate::app; + #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; -use crate::app; use std::any::type_name; diff --git a/pagetop/src/module/mod.rs b/pagetop/src/module/mod.rs index cb71dfd2..faf51e8b 100644 --- a/pagetop/src/module/mod.rs +++ b/pagetop/src/module/mod.rs @@ -1,17 +1,4 @@ -use crate::{all, trace}; - mod definition; pub use definition::ModuleTrait; -pub mod homepage; - -pub fn register_module(m: &'static dyn ModuleTrait) { - let mut modules = all::MODULES.write().unwrap(); - match modules.iter().find(|t| t.name() == m.name()) { - None => { - trace::info!("{}", m.name()); - modules.push(m); - }, - Some(_) => {}, - } -} +pub use crate::global::register_module; diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 1bfc1817..e9b3617c 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -16,6 +16,6 @@ pub use crate::response::page::*; pub use crate::app; pub use crate::app::application::{Application, essence}; -pub use crate::component::*; +pub use crate::base::component::*; pub use crate::util; diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index 9c30d981..99e42b06 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -1,17 +1,7 @@ -use crate::{Lazy, all}; -use crate::config::SETTINGS; +use crate::global::DEFAULT_THEME; use crate::html::{Markup, PreEscaped, html}; use crate::theme::*; -static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - for t in all::THEMES.read().unwrap().iter() { - if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() { - return *t; - } - } - &bootsier::BootsierTheme -}); - // ----------------------------------------------------------------------------- // Favicon. // ----------------------------------------------------------------------------- @@ -207,7 +197,7 @@ impl PageAssets { } pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.theme = find_theme(theme_name).unwrap_or(*DEFAULT_THEME); + self.theme = theme_by_name(theme_name).unwrap_or(*DEFAULT_THEME); self } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 38ad1bfd..727df347 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,8 +1,8 @@ +use crate::app; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::response::page::{Page, PageAssets, PageComponent}; -use crate::app; -use crate::component::Chunck; +use crate::base::component::Chunck; /// Los temas deben implementar este "trait". pub trait ThemeTrait: Send + Sync { diff --git a/pagetop/src/theme/mod.rs b/pagetop/src/theme/mod.rs index 9b045708..a1d0e4ca 100644 --- a/pagetop/src/theme/mod.rs +++ b/pagetop/src/theme/mod.rs @@ -1,20 +1,5 @@ -use crate::all; - mod definition; pub use definition::ThemeTrait; -pub mod aliner; -pub mod minimal; -pub mod bootsier; - -pub fn register_theme(t: &'static dyn ThemeTrait) { - all::THEMES.write().unwrap().push(t); -} - -pub fn find_theme(name: &str) -> Option<&'static dyn ThemeTrait> { - let themes = all::THEMES.write().unwrap(); - match themes.iter().find(|t| t.name() == name) { - Some(theme) => Some(*theme), - _ => None, - } -} +pub use crate::global::register_theme; +pub use crate::global::theme_by_name; From e3f592b3b0835e758e0aca1e3dcec038d924de09 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 20 Mar 2022 20:48:54 +0100 Subject: [PATCH 06/80] =?UTF-8?q?A=C3=B1ade=20carga=20de=20archivos=20est?= =?UTF-8?q?=C3=A1ticos=20desde=20directorio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Con el ajuste de configuración "dev.static_files" se puede elegir entre integrar los archivos estáticos en el binario ejecutable (por defecto) o servirlos desde su propio directorio. Esto facilita el desarrollo al no tener que compilar cada vez que se modifican estos archivos. --- config/default.toml | 7 +++++-- drust/Cargo.toml | 2 +- pagetop-admin/Cargo.toml | 6 +++--- pagetop-node/Cargo.toml | 4 ++-- pagetop-user/Cargo.toml | 10 +++------ pagetop-user/src/locales/es-ES/homepage.ftl | 2 +- pagetop/Cargo.toml | 13 ++++++------ pagetop/STARTER.bin.Cargo.toml | 18 +++++++--------- pagetop/STARTER.lib.Cargo.toml | 23 +++++---------------- pagetop/build.rs | 3 --- pagetop/config/settings.default.toml | 8 +++++++ pagetop/src/base/theme/aliner/mod.rs | 5 +---- pagetop/src/base/theme/bootsier/mod.rs | 7 ++----- pagetop/src/config.rs | 11 +++++++++- pagetop/src/global.rs | 7 ++----- pagetop/src/prelude.rs | 7 ++++++- pagetop/src/util.rs | 18 ++++++++++++++++ pagetop/static/aliner/css/styles.css | 13 ++++++++++++ 18 files changed, 93 insertions(+), 71 deletions(-) diff --git a/config/default.toml b/config/default.toml index 33280fbd..5b6982fe 100644 --- a/config/default.toml +++ b/config/default.toml @@ -1,12 +1,12 @@ [app] name = "Drust" description = """\ - A modern Content Management System for sharing the world.\ + A modern web Content Management System to share your world.\ """ -language = "es-ES" #theme = "Aliner" #theme = "Minimal" theme = "Bootsier" +language = "es-ES" [database] db_type = "mysql" @@ -16,3 +16,6 @@ db_pass = "DrU__#3T" [log] tracing = "Info,sqlx::query=Warn" + +[dev] +#static_files = "pagetop/static" diff --git a/drust/Cargo.toml b/drust/Cargo.toml index 88ebabde..7a5412d5 100644 --- a/drust/Cargo.toml +++ b/drust/Cargo.toml @@ -7,7 +7,7 @@ authors = [ "Manuel Cillero " ] description = """\ - A modern Content Management System for sharing the world.\ + A modern web Content Management System to share your world.\ """ homepage = "https://suitepro.cillero.es/projects/drust" repository = "https://gitlab.com/manuelcillero/drust" diff --git a/pagetop-admin/Cargo.toml b/pagetop-admin/Cargo.toml index 1bff0edd..3dfc6e60 100644 --- a/pagetop-admin/Cargo.toml +++ b/pagetop-admin/Cargo.toml @@ -7,10 +7,10 @@ authors = [ "Manuel Cillero " ] description = """\ - Allows content to be submitted to the site and displayed on pages.\ + ...\ """ -homepage = "https://suitepro.cillero.es/projects/drust" -repository = "https://gitlab.com/manuelcillero/drust" +homepage = "https://suitepro.cillero.es/projects/pagetop" +repository = "https://gitlab.com/manuelcillero/pagetop" [dependencies] pagetop = { path = "../pagetop" } diff --git a/pagetop-node/Cargo.toml b/pagetop-node/Cargo.toml index 36b43d39..29857822 100644 --- a/pagetop-node/Cargo.toml +++ b/pagetop-node/Cargo.toml @@ -9,8 +9,8 @@ authors = [ description = """\ Allows content to be submitted to the site and displayed on pages.\ """ -homepage = "https://suitepro.cillero.es/projects/drust" -repository = "https://gitlab.com/manuelcillero/drust" +homepage = "https://suitepro.cillero.es/projects/pagetop" +repository = "https://gitlab.com/manuelcillero/pagetop" [dependencies] pagetop = { path = "../pagetop" } diff --git a/pagetop-user/Cargo.toml b/pagetop-user/Cargo.toml index 37352fe7..59c24cb3 100644 --- a/pagetop-user/Cargo.toml +++ b/pagetop-user/Cargo.toml @@ -9,14 +9,10 @@ authors = [ description = """\ Allows content to be submitted to the site and displayed on pages.\ """ -homepage = "https://suitepro.cillero.es/projects/drust" -repository = "https://gitlab.com/manuelcillero/drust" +homepage = "https://suitepro.cillero.es/projects/pagetop" +repository = "https://gitlab.com/manuelcillero/pagetop" [dependencies] pagetop = { path = "../pagetop" } +sea-orm = { version = "0.6.0" } serde = { version = "1.0", features = ["derive"] } - -[dependencies.sea-orm] -version = "0.6.0" -features = ["debug-print", "macros"] -default-features = false diff --git a/pagetop-user/src/locales/es-ES/homepage.ftl b/pagetop-user/src/locales/es-ES/homepage.ftl index ae9a70e0..f5f6e1bb 100644 --- a/pagetop-user/src/locales/es-ES/homepage.ftl +++ b/pagetop-user/src/locales/es-ES/homepage.ftl @@ -1,5 +1,5 @@ module_fullname = Usuario -module_description = Gestion el registro de usuarios y el sistema de accesos. +module_description = Gestiona el registro de usuarios y el sistema de accesos. username = Nombre de usuario password = Contraseña diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index db491819..4d92b378 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -7,10 +7,8 @@ authors = [ "Manuel Cillero " ] description = """\ - PageTop es un proyecto personal para aprender Rust. Incluye algunos de los \ - crates más estables y populares para desarrollar soluciones web modulares, \ - extensibles y configurables. También es un sistema para la gestión de \ - contenidos web.\ + PageTop is an opinionated framework for using the most stable and popular \ + Rust packages to build modular, extensible and configurable web solutions.\ """ homepage = "https://suitepro.cillero.es/projects/pagetop" repository = "https://gitlab.com/manuelcillero/pagetop" @@ -44,6 +42,7 @@ unic-langid = "0.9.0" actix-web = "3.3.3" actix-web-static-files = "3.0.5" +actix-files = "0.4.1" maud = { version = "0.23.0", features = ["actix-web"] } sycamore = { version = "0.7.1", features = ["ssr"] } @@ -62,9 +61,6 @@ features = ["debug-print", "migration"] default-features = false optional = true -[dev-dependencies] -tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } - [features] default = [] mysql = ["sea-orm", "sea-schema", "sea-orm/sqlx-mysql"] @@ -74,5 +70,8 @@ sqlite = ["sea-orm", "sea-schema", "sea-orm/sqlx-sqlite"] [build-dependencies] actix-web-static-files = "3.0.5" +[dev-dependencies] +tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } + [lib] name = "pagetop" diff --git a/pagetop/STARTER.bin.Cargo.toml b/pagetop/STARTER.bin.Cargo.toml index d05a17bf..2ee2fd9d 100644 --- a/pagetop/STARTER.bin.Cargo.toml +++ b/pagetop/STARTER.bin.Cargo.toml @@ -8,24 +8,20 @@ edition = "2021" [dependencies.pagetop] path = "../pagetop" -# Opcional. Por defecto se puede usar PageTop sin base de datos. +# PageTop por defecto no requiere base de datos. Hay que habilitarla: features = ["mysql"] # features = ["postgres"] # features = ["sqlite"] -# PageTop puede dar soporte a todas las bases de datos. +# PageTop puede dar soporte a todas las bases de datos: # features = ["mysql", "postgres", "sqlite"] -# Sólo cuando no se usen las características predeterminadas. +# En estos casos hay que deshabilitar las características predeterminadas: default-features = false [dependencies] -# Requerido. actix-web = "3.3.3" -# Opcional. Sólo si se usa la macro html!. +# Opcional. Sólo si se usa la macro html!: maud = { version = "0.23.0" } -# Opcional. Si se requiere serialización de estructuras de datos. +# Opcional. Sólo si se usa base de datos: +sea-orm = { version = "0.6.0" } +# Opcional. Para la serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } - -[dependencies.sea-orm] -version = "0.6.0" -features = ["debug-print", "macros"] -default-features = false diff --git a/pagetop/STARTER.lib.Cargo.toml b/pagetop/STARTER.lib.Cargo.toml index 97389750..74e74a8a 100644 --- a/pagetop/STARTER.lib.Cargo.toml +++ b/pagetop/STARTER.lib.Cargo.toml @@ -6,24 +6,11 @@ edition = "2021" # Ver más claves y sus definiciones en # https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies.pagetop] -path = "../pagetop" -# Opcional. Por defecto se puede usar PageTop sin base de datos. -features = ["mysql"] -# features = ["postgres"] -# features = ["sqlite"] -# PageTop puede dar soporte a todas las bases de datos. -# features = ["mysql", "postgres", "sqlite"] -# Sólo cuando no se usen las características predeterminadas. -default-features = false - [dependencies] -# Opcional. Sólo si se usa la macro html!. +pagetop = { path = "../pagetop" } +# Opcional. Sólo si se usa la macro html!: maud = { version = "0.23.0" } -# Opcional. Si se requiere serialización de estructuras de datos. +# Opcional. Sólo si se usa base de datos: +sea-orm = { version = "0.6.0" } +# Opcional. Para la serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } - -[dependencies.sea-orm] -version = "0.6.0" -features = ["debug-print", "macros"] -default-features = false diff --git a/pagetop/build.rs b/pagetop/build.rs index 9b252213..bd7e60a0 100644 --- a/pagetop/build.rs +++ b/pagetop/build.rs @@ -9,7 +9,6 @@ fn main() { Path::new(env::var("OUT_DIR").unwrap().as_str()) .join("theme.rs") ) - .with_generated_fn("assets") .build() .unwrap(); @@ -18,7 +17,6 @@ fn main() { Path::new(env::var("OUT_DIR").unwrap().as_str()) .join("aliner.rs") ) - .with_generated_fn("assets") .build() .unwrap(); @@ -27,7 +25,6 @@ fn main() { Path::new(env::var("OUT_DIR").unwrap().as_str()) .join("bootsier.rs") ) - .with_generated_fn("assets") .build() .unwrap(); } diff --git a/pagetop/config/settings.default.toml b/pagetop/config/settings.default.toml index b9c329cf..8ac7ab2d 100644 --- a/pagetop/config/settings.default.toml +++ b/pagetop/config/settings.default.toml @@ -43,3 +43,11 @@ max_pool_size = 5 # Configuración del servidor web. bind_address = "localhost" bind_port = 8088 + +[dev] +# Los archivos estáticos requeridos por temas y componentes incluidos en PageTop +# se integran de manera predeterminada en el binario ejecutable. Sin embargo, es +# útil servir estos archivos desde su propio directorio durante el desarrollo ya +# que no requiere compilar cada vez que se modifican. En este caso, normalmente, +# basta con indicar el directorio "pagetop/static". +static_files = "" diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index 676eb25d..07b1470f 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -14,10 +14,7 @@ impl ThemeTrait for AlinerTheme { } fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { - cfg.service(actix_web_static_files::ResourceFiles::new( - "/aliner", - assets() - )); + theme_static_files!(cfg, "/aliner"); } fn before_render_page(&self, page: &mut Page) { diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index 132dce32..dbd31727 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -16,10 +16,7 @@ impl ThemeTrait for BootsierTheme { } fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { - cfg.service(actix_web_static_files::ResourceFiles::new( - "/bootsier", - assets() - )); + theme_static_files!(cfg, "/bootsier"); } fn before_render_page(&self, page: &mut Page) { @@ -61,7 +58,7 @@ impl ThemeTrait for BootsierTheme { div class="jumbotron" { div class="media" { img - src="/bootsier/images/caution.png" + src="/static/bootsier/images/caution.png" class="mr-4" style="width: 20%; max-width: 188px" alt="Caution!"; diff --git a/pagetop/src/config.rs b/pagetop/src/config.rs index 27dbb275..0a5e322d 100644 --- a/pagetop/src/config.rs +++ b/pagetop/src/config.rs @@ -104,12 +104,18 @@ pub struct Webserver { pub bind_port : u16, } +#[derive(Debug, Deserialize)] +pub struct Dev { + pub static_files : String, +} + #[derive(Debug, Deserialize)] pub struct Settings { pub app : App, pub log : Log, pub database : Database, pub webserver : Webserver, + pub dev : Dev, } config_map!(r#" @@ -144,5 +150,8 @@ Ajustes globales y valores predeterminados para las secciones *\[app\]*, // [webserver] "webserver.bind_address" => "localhost", - "webserver.bind_port" => 8088 + "webserver.bind_port" => 8088, + + // [dev] + "dev.static_files" => "" ); diff --git a/pagetop/src/global.rs b/pagetop/src/global.rs index 34280cf4..1b4c169f 100644 --- a/pagetop/src/global.rs +++ b/pagetop/src/global.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, app, base, run_now, trace}; +use crate::{Lazy, app, base, run_now, theme_static_files, trace}; use crate::config::SETTINGS; use crate::db::migration::*; use crate::module::*; @@ -84,10 +84,7 @@ pub fn theme_by_name(name: &str) -> Option<&'static dyn ThemeTrait> { } pub fn themes(cfg: &mut app::web::ServiceConfig) { - cfg.service(actix_web_static_files::ResourceFiles::new( - "/theme", - assets() - )); + theme_static_files!(cfg, "/theme"); for t in THEMES.read().unwrap().iter() { t.configure_theme(cfg); diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index e9b3617c..7c2e9ef3 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -1,6 +1,11 @@ //! Re-exporta recursos comunes. -pub use crate::args; +// Macros. +pub use crate::{ + args, + theme_static_files, +}; + pub use crate::config::SETTINGS; pub use crate::trace; pub use crate::localize; diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index 3fff0a23..c5254618 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -18,6 +18,24 @@ macro_rules! args { }}; } +#[macro_export] +macro_rules! theme_static_files { + ( $cfg:ident, $dir:expr ) => {{ + let static_files = &$crate::config::SETTINGS.dev.static_files; + if static_files.is_empty() { + $cfg.service(actix_web_static_files::ResourceFiles::new( + $dir, + generate() + )); + } else { + $cfg.service(actix_files::Files::new( + $dir, + &[static_files, $dir].join("") + ).show_files_listing()); + } + }}; +} + pub fn valid_id(id: &str) -> Option { let id = id.trim().replace(" ", "_").to_lowercase(); match id.is_empty() { diff --git a/pagetop/static/aliner/css/styles.css b/pagetop/static/aliner/css/styles.css index ffeee7db..1cc2f5dc 100644 --- a/pagetop/static/aliner/css/styles.css +++ b/pagetop/static/aliner/css/styles.css @@ -1,5 +1,16 @@ html { background-color: white; + padding: 1px 3px; +} +body { + padding: 1px 3px; +} +div { + padding: 1px 3px; + margin: 5px; +} +h1, h2, h3, h4,h5, h6, p { + background-color: snow; } * * { outline: 5px solid rgba(255,0,0,.1); @@ -21,7 +32,9 @@ html { background: #faa; border-radius: 3px; font: normal normal 400 10px/1.2 monospace; + vertical-align: middle; padding: 1px 3px; + margin: 0 3px; } *::before { content: "("; From d72e1ccad56221bdafec9568dfb2e443272c7347 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 23 Mar 2022 22:29:07 +0100 Subject: [PATCH 07/80] =?UTF-8?q?Actualiza=20la=20presentaci=C3=B3n=20del?= =?UTF-8?q?=20r=C3=B3tulo=20de=20arranque?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/STARTER.bin.Cargo.toml | 10 +- pagetop/STARTER.lib.Cargo.toml | 6 +- pagetop/config/settings.default.toml | 4 +- pagetop/src/app/application.rs | 40 ++------ pagetop/src/app/banner/mod.rs | 40 ++++++++ .../src/app/{figfonts => banner}/slant.flf | 0 .../src/app/{figfonts => banner}/small.flf | 0 .../src/app/{figfonts => banner}/speed.flf | 0 .../src/app/{figfonts => banner}/starwars.flf | 0 pagetop/src/app/mod.rs | 2 + pagetop/src/config.rs | 2 +- pagetop/src/global.rs | 93 ------------------- pagetop/src/lib.rs | 2 - pagetop/src/module/all.rs | 44 +++++++++ pagetop/src/module/mod.rs | 3 +- pagetop/src/response/page/assets.rs | 10 +- pagetop/src/theme/all.rs | 43 +++++++++ pagetop/src/theme/mod.rs | 7 +- 18 files changed, 164 insertions(+), 142 deletions(-) create mode 100644 pagetop/src/app/banner/mod.rs rename pagetop/src/app/{figfonts => banner}/slant.flf (100%) rename pagetop/src/app/{figfonts => banner}/small.flf (100%) rename pagetop/src/app/{figfonts => banner}/speed.flf (100%) rename pagetop/src/app/{figfonts => banner}/starwars.flf (100%) delete mode 100644 pagetop/src/global.rs create mode 100644 pagetop/src/module/all.rs create mode 100644 pagetop/src/theme/all.rs diff --git a/pagetop/STARTER.bin.Cargo.toml b/pagetop/STARTER.bin.Cargo.toml index 2ee2fd9d..9c6c8979 100644 --- a/pagetop/STARTER.bin.Cargo.toml +++ b/pagetop/STARTER.bin.Cargo.toml @@ -8,20 +8,20 @@ edition = "2021" [dependencies.pagetop] path = "../pagetop" -# PageTop por defecto no requiere base de datos. Hay que habilitarla: +# Si se usa base de datos: features = ["mysql"] # features = ["postgres"] # features = ["sqlite"] -# PageTop puede dar soporte a todas las bases de datos: +# Soporte alternativo a todas las bases de datos: # features = ["mysql", "postgres", "sqlite"] # En estos casos hay que deshabilitar las características predeterminadas: default-features = false [dependencies] actix-web = "3.3.3" -# Opcional. Sólo si se usa la macro html!: +# Si se usa la macro html!: maud = { version = "0.23.0" } -# Opcional. Sólo si se usa base de datos: +# Si se usa base de datos: sea-orm = { version = "0.6.0" } -# Opcional. Para la serialización de estructuras de datos: +# Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/STARTER.lib.Cargo.toml b/pagetop/STARTER.lib.Cargo.toml index 74e74a8a..e98fed13 100644 --- a/pagetop/STARTER.lib.Cargo.toml +++ b/pagetop/STARTER.lib.Cargo.toml @@ -8,9 +8,9 @@ edition = "2021" [dependencies] pagetop = { path = "../pagetop" } -# Opcional. Sólo si se usa la macro html!: +# Si se usa la macro html!: maud = { version = "0.23.0" } -# Opcional. Sólo si se usa base de datos: +# Si se usa base de datos: sea-orm = { version = "0.6.0" } -# Opcional. Para la serialización de estructuras de datos: +# Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/config/settings.default.toml b/pagetop/config/settings.default.toml index 8ac7ab2d..115b4cb7 100644 --- a/pagetop/config/settings.default.toml +++ b/pagetop/config/settings.default.toml @@ -8,7 +8,7 @@ language = "en-US" # Dirección predeterminada para el texto: "ltr", "rtl" o "auto". direction = "ltr" # Rótulo al inicio: "Off", "Slant", "Small", "Speed" o "Starwars". -startup_banner = "Small" +startup_banner = "Slant" [log] # Traza de ejecución: "Error", "Warn", "Info", "Debug" o "Trace". @@ -25,7 +25,7 @@ format = "Full" [database] # Conecta con una base de datos (opcional). -# Tipo de la base de datos (mysql, postgres ó sqlite). +# Tipo de base de datos (mysql, postgres ó sqlite). db_type = "" # Nombre (para mysql/postgres) o referencia (para sqlite) de la base de datos. db_name = "" diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 274203e6..4ed2c1da 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -1,6 +1,5 @@ -use crate::{Lazy, app, base, global, trace}; +use crate::{Lazy, app, base, module, theme, trace}; use crate::config::SETTINGS; -use crate::module::register_module; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; @@ -15,31 +14,8 @@ pub fn essence() { impl Application { pub async fn prepare(bootstrap: fn()) -> Result { - // Imprime un rótulo de presentación (opcional). - if SETTINGS.app.startup_banner.to_lowercase() != "off" { - let figfont = figlet_rs::FIGfont::from_content( - match SETTINGS.app.startup_banner.to_lowercase().as_str() { - "slant" => include_str!("figfonts/slant.flf"), - "small" => include_str!("figfonts/small.flf"), - "speed" => include_str!("figfonts/speed.flf"), - "starwars" => include_str!("figfonts/starwars.flf"), - _ => { - println!( - "FIGfont \"{}\" not found for banner. {}. {}.", - SETTINGS.app.startup_banner, - "Using \"Small\"", - "Check the settings file", - ); - include_str!("figfonts/small.flf") - } - } - ).unwrap(); - println!("\n{} {}\n\n Powered by PageTop {}\n", - figfont.convert(&SETTINGS.app.name).unwrap(), - &SETTINGS.app.description, - env!("CARGO_PKG_VERSION") - ); - } + // Rótulo de presentación. + app::banner::print_on_startup(); // Inicia registro de trazas y eventos. Lazy::force(&app::tracing::TRACING); @@ -57,19 +33,19 @@ impl Application { // Registra el módulo para una página de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. - register_module(&base::module::homepage::HomepageModule); + module::register_module(&base::module::homepage::HomepageModule); - // Comprueba actualizaciones pendientes de la base de datos (opcional). + // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - global::run_migrations(); + module::all::migrations(); // Prepara el servidor web. let server = app::HttpServer::new(move || { app::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(NormalizePath::new(TrailingSlash::Trim)) - .configure(&global::themes) - .configure(&global::modules) + .configure(&module::all::modules) + .configure(&theme::all::themes) }) .bind(format!("{}:{}", &SETTINGS.webserver.bind_address, diff --git a/pagetop/src/app/banner/mod.rs b/pagetop/src/app/banner/mod.rs new file mode 100644 index 00000000..f6d63841 --- /dev/null +++ b/pagetop/src/app/banner/mod.rs @@ -0,0 +1,40 @@ +use crate::Lazy; +use crate::config::SETTINGS; + +use figlet_rs::FIGfont; + +static FIGFONT: Lazy = Lazy::new(|| { + let slant = include_str!("slant.flf"); + let small = include_str!("small.flf"); + let speed = include_str!("speed.flf"); + let starwars = include_str!("starwars.flf"); + + FIGfont::from_content( + match SETTINGS.app.startup_banner.to_lowercase().as_str() { + "off" => slant, + "slant" => slant, + "small" => small, + "speed" => speed, + "starwars" => starwars, + _ => { + println!( + "\n FIGfont \"{}\" not found for banner. {}. {}.", + SETTINGS.app.startup_banner, + "Using \"Slant\"", + "Check the settings file", + ); + slant + } + } + ).unwrap() +}); + +pub fn print_on_startup() { + if SETTINGS.app.startup_banner.to_lowercase() != "off" { + println!("\n{} {}\n\n Powered by PageTop {}\n", + FIGFONT.convert(&SETTINGS.app.name).unwrap(), + &SETTINGS.app.description, + env!("CARGO_PKG_VERSION") + ); + } +} diff --git a/pagetop/src/app/figfonts/slant.flf b/pagetop/src/app/banner/slant.flf similarity index 100% rename from pagetop/src/app/figfonts/slant.flf rename to pagetop/src/app/banner/slant.flf diff --git a/pagetop/src/app/figfonts/small.flf b/pagetop/src/app/banner/small.flf similarity index 100% rename from pagetop/src/app/figfonts/small.flf rename to pagetop/src/app/banner/small.flf diff --git a/pagetop/src/app/figfonts/speed.flf b/pagetop/src/app/banner/speed.flf similarity index 100% rename from pagetop/src/app/figfonts/speed.flf rename to pagetop/src/app/banner/speed.flf diff --git a/pagetop/src/app/figfonts/starwars.flf b/pagetop/src/app/banner/starwars.flf similarity index 100% rename from pagetop/src/app/figfonts/starwars.flf rename to pagetop/src/app/banner/starwars.flf diff --git a/pagetop/src/app/mod.rs b/pagetop/src/app/mod.rs index b3f7cd6a..07404f64 100644 --- a/pagetop/src/app/mod.rs +++ b/pagetop/src/app/mod.rs @@ -3,6 +3,8 @@ pub use actix_web::{ }; use actix_web::dev::Server; +mod banner; + mod tracing; pub mod locale; diff --git a/pagetop/src/config.rs b/pagetop/src/config.rs index 0a5e322d..775cc4a6 100644 --- a/pagetop/src/config.rs +++ b/pagetop/src/config.rs @@ -130,7 +130,7 @@ Ajustes globales y valores predeterminados para las secciones *\[app\]*, "app.theme" => "Bootsier", "app.language" => "en-US", "app.direction" => "ltr", - "app.startup_banner" => "Small", + "app.startup_banner" => "Slant", // [log] "log.tracing" => "Info", diff --git a/pagetop/src/global.rs b/pagetop/src/global.rs deleted file mode 100644 index 1b4c169f..00000000 --- a/pagetop/src/global.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::{Lazy, app, base, run_now, theme_static_files, trace}; -use crate::config::SETTINGS; -use crate::db::migration::*; -use crate::module::*; -use crate::theme::*; - -use std::sync::RwLock; - -// ----------------------------------------------------------------------------- -// Módulos registrados. -// ----------------------------------------------------------------------------- - -pub static MODULES: Lazy>> = Lazy::new( - || { RwLock::new(Vec::new()) } -); - -pub fn register_module(m: &'static dyn ModuleTrait) { - let mut modules = MODULES.write().unwrap(); - match modules.iter().find(|t| t.name() == m.name()) { - None => { - trace::info!("{}", m.name()); - modules.push(m); - }, - Some(_) => {}, - } -} - -pub fn modules(cfg: &mut app::web::ServiceConfig) { - for m in MODULES.read().unwrap().iter() { - m.configure_module(cfg); - } -} - -#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub fn run_migrations() { - run_now({ - struct Migrator; - impl MigratorTrait for Migrator { - fn migrations() -> Vec> { - let mut migrations = vec![]; - for m in MODULES.read().unwrap().iter() { - migrations.append(&mut m.migrations()); - } - migrations - } - } - Migrator::up(&app::db::DBCONN, None) - }).unwrap(); -} - -// ----------------------------------------------------------------------------- -// Temas registrados y tema predeterminado. -// ----------------------------------------------------------------------------- - -include!(concat!(env!("OUT_DIR"), "/theme.rs")); - -pub static THEMES: Lazy>> = Lazy::new(|| { - RwLock::new(vec![ - &base::theme::aliner::AlinerTheme, - &base::theme::minimal::MinimalTheme, - &base::theme::bootsier::BootsierTheme, - ]) -}); - -pub static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - for t in THEMES.read().unwrap().iter() { - if t.name().to_lowercase() == SETTINGS.app.theme.to_lowercase() { - return *t; - } - } - &base::theme::bootsier::BootsierTheme -}); - -pub fn register_theme(t: &'static dyn ThemeTrait) { - THEMES.write().unwrap().push(t); -} - -pub fn theme_by_name(name: &str) -> Option<&'static dyn ThemeTrait> { - let themes = crate::global::THEMES.write().unwrap(); - match themes.iter().find(|t| t.name() == name) { - Some(theme) => Some(*theme), - _ => None, - } -} - -pub fn themes(cfg: &mut app::web::ServiceConfig) { - theme_static_files!(cfg, "/theme"); - - for t in THEMES.read().unwrap().iter() { - t.configure_theme(cfg); - } -} - diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 3efe21aa..73e17c8d 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -8,8 +8,6 @@ pub use futures::executor::block_on as run_now; // APIs públicas. // ----------------------------------------------------------------------------- -mod global; // Ref. privadas globales a todos los temas y módulos. - pub mod config; // Gestión de la configuración. pub mod trace; // Registro de trazas y eventos de la aplicación. pub mod locale; // Localización. diff --git a/pagetop/src/module/all.rs b/pagetop/src/module/all.rs new file mode 100644 index 00000000..120c59b6 --- /dev/null +++ b/pagetop/src/module/all.rs @@ -0,0 +1,44 @@ +use crate::{Lazy, app, run_now, trace}; +use crate::db::migration::*; +use super::ModuleTrait; + +use std::sync::RwLock; + +// Módulos registrados. +static MODULES: Lazy>> = Lazy::new(|| { + RwLock::new(Vec::new()) +}); + +pub fn register_module(module: &'static dyn ModuleTrait) { + let mut modules = MODULES.write().unwrap(); + match modules.iter().find(|m| m.name() == module.name()) { + None => { + trace::info!("{}", module.name()); + modules.push(module); + }, + Some(_) => {}, + } +} + +pub fn modules(cfg: &mut app::web::ServiceConfig) { + for m in MODULES.read().unwrap().iter() { + m.configure_module(cfg); + } +} + +#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] +pub fn migrations() { + run_now({ + struct Migrator; + impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + let mut migrations = vec![]; + for m in MODULES.read().unwrap().iter() { + migrations.append(&mut m.migrations()); + } + migrations + } + } + Migrator::up(&app::db::DBCONN, None) + }).unwrap(); +} diff --git a/pagetop/src/module/mod.rs b/pagetop/src/module/mod.rs index faf51e8b..a767683b 100644 --- a/pagetop/src/module/mod.rs +++ b/pagetop/src/module/mod.rs @@ -1,4 +1,5 @@ mod definition; pub use definition::ModuleTrait; -pub use crate::global::register_module; +pub(crate) mod all; +pub use all::register_module; \ No newline at end of file diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index 99e42b06..ffc566ea 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -1,7 +1,15 @@ -use crate::global::DEFAULT_THEME; +use crate::{Lazy, base}; +use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; use crate::theme::*; +static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { + match theme_by_name(&SETTINGS.app.theme) { + Some(theme) => theme, + None => &base::theme::bootsier::BootsierTheme, + } +}); + // ----------------------------------------------------------------------------- // Favicon. // ----------------------------------------------------------------------------- diff --git a/pagetop/src/theme/all.rs b/pagetop/src/theme/all.rs new file mode 100644 index 00000000..cc25d9d8 --- /dev/null +++ b/pagetop/src/theme/all.rs @@ -0,0 +1,43 @@ +use crate::{Lazy, app, base, theme_static_files, trace}; +use super::ThemeTrait; + +use std::sync::RwLock; + +include!(concat!(env!("OUT_DIR"), "/theme.rs")); + +// Temas registrados. +static THEMES: Lazy>> = Lazy::new(|| { + RwLock::new(vec![ + &base::theme::aliner::AlinerTheme, + &base::theme::minimal::MinimalTheme, + &base::theme::bootsier::BootsierTheme, + ]) +}); + +pub fn register_theme(theme: &'static dyn ThemeTrait) { + let mut themes = THEMES.write().unwrap(); + match themes.iter().find(|t| t.name() == theme.name()) { + None => { + trace::info!("{}", theme.name()); + themes.push(theme); + }, + Some(_) => {}, + } +} + +pub fn theme_by_name(name: &str) -> Option<&'static dyn ThemeTrait> { + match THEMES.write().unwrap().iter().find( + |t| t.name().to_lowercase() == name.to_lowercase() + ) { + Some(theme) => Some(*theme), + _ => None, + } +} + +pub fn themes(cfg: &mut app::web::ServiceConfig) { + theme_static_files!(cfg, "/theme"); + + for t in THEMES.read().unwrap().iter() { + t.configure_theme(cfg); + } +} diff --git a/pagetop/src/theme/mod.rs b/pagetop/src/theme/mod.rs index a1d0e4ca..4456189e 100644 --- a/pagetop/src/theme/mod.rs +++ b/pagetop/src/theme/mod.rs @@ -1,5 +1,8 @@ mod definition; pub use definition::ThemeTrait; -pub use crate::global::register_theme; -pub use crate::global::theme_by_name; +pub(crate) mod all; +pub use all::{ + register_theme, + theme_by_name, +}; From 5b1064fda2a4ffd6f7bbdbc87b98d2a0b2a4762c Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 25 Mar 2022 20:24:19 +0100 Subject: [PATCH 08/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CREDITS.md | 11 ++++++-- config/default.toml | 2 +- pagetop-admin/src/lib.rs | 4 +++ pagetop-node/src/lib.rs | 4 +++ pagetop-user/src/lib.rs | 4 +++ pagetop/Cargo.toml | 2 +- pagetop/src/app/application.rs | 9 +++++-- pagetop/src/base/component/block.rs | 2 +- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 8 +++--- pagetop/src/base/component/form/form.rs | 4 +-- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 8 +++--- .../locales/en-US/demopage.ftl} | 2 +- .../locales/es-ES/demopage.ftl} | 2 +- .../base/module/{homepage => demopage}/mod.rs | 14 +++++++--- pagetop/src/base/module/mod.rs | 2 +- pagetop/src/base/theme/aliner/mod.rs | 6 ++++- pagetop/src/base/theme/bootsier/mod.rs | 4 +-- pagetop/src/base/theme/minimal/mod.rs | 2 +- pagetop/src/module/all.rs | 25 +++++++++++++----- pagetop/src/module/definition.rs | 10 +------ pagetop/src/response/page/page.rs | 6 ++--- pagetop/src/theme/all.rs | 17 ++++-------- pagetop/src/theme/definition.rs | 7 ++++- pagetop/src/util.rs | 12 ++++----- pagetop/static/theme/favicon.png | Bin 0 -> 11471 bytes 27 files changed, 104 insertions(+), 67 deletions(-) rename pagetop/src/base/module/{homepage/locales/en-US/homepage.ftl => demopage/locales/en-US/demopage.ftl} (95%) rename pagetop/src/base/module/{homepage/locales/es-ES/homepage.ftl => demopage/locales/es-ES/demopage.ftl} (93%) rename pagetop/src/base/module/{homepage => demopage}/mod.rs (91%) create mode 100644 pagetop/static/theme/favicon.png diff --git a/CREDITS.md b/CREDITS.md index 5b9979f4..4254ed59 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,9 +1,9 @@ # FIGfonts PageTop utiliza el paquete [figlet-rs](https://crates.io/crates/figlet-rs) de -*yuanbohan*, que muestra al inicio de la ejecución un rótulo con el nombre de +*yuanbohan*. Muestra en el terminal un rótulo de presentación con el nombre de la aplicación usando caracteres [FIGlet](http://www.figlet.org/). Las fuentes -incluidas en `resources` son: +incluidas en `src/app/banner` son: * [slant.flf](http://www.figlet.org/fontdb_example.cgi?font=slant.flf) por *Glenn Chappell*. @@ -13,3 +13,10 @@ incluidas en `resources` son: por *Claude Martins*. * [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf) por *Ryan Youck*. + +# Icono + +El monstruo sonriente de Frankenstein es una divertida creación de +[Webalys](https://www.iconfinder.com/webalys). Puede encontrarse en su colección +[Nasty Icons](https://www.iconfinder.com/iconsets/nasty) disponible en +[ICONFINDER](https://www.iconfinder.com/). \ No newline at end of file diff --git a/config/default.toml b/config/default.toml index 5b6982fe..13012a93 100644 --- a/config/default.toml +++ b/config/default.toml @@ -15,7 +15,7 @@ db_user = "drust" db_pass = "DrU__#3T" [log] -tracing = "Info,sqlx::query=Warn" +tracing = "Info,pagetop=Debug,sqlx::query=Warn" [dev] #static_files = "pagetop/static" diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index e3ad0337..a00e7fae 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -7,6 +7,10 @@ mod summary; pub struct AdminModule; impl ModuleTrait for AdminModule { + fn name(&self) -> &'static str { + "Admin" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index af6d8b3f..afcd729f 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -8,6 +8,10 @@ mod migration; pub struct NodeModule; impl ModuleTrait for NodeModule { + fn name(&self) -> &'static str { + "Node" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index c76233e1..343daa7a 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -8,6 +8,10 @@ mod migration; pub struct UserModule; impl ModuleTrait for UserModule { + fn name(&self) -> &'static str { + "User" + } + fn fullname(&self) -> String { l("module_fullname") } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 4d92b378..a260d17f 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.3" +version = "0.0.4" edition = "2021" authors = [ diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 4ed2c1da..070390c8 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -27,13 +27,18 @@ impl Application { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] Lazy::force(&app::db::DBCONN); + // Registra los temas predeterminados. + theme::register_theme(&base::theme::aliner::AlinerTheme); + theme::register_theme(&base::theme::minimal::MinimalTheme); + theme::register_theme(&base::theme::bootsier::BootsierTheme); + // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); let _ = &bootstrap(); - // Registra el módulo para una página de presentación de PageTop. + // Registra el módulo de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. - module::register_module(&base::module::homepage::HomepageModule); + module::register_module(&base::module::demopage::DemopageModule); // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 4f658c9e..96fce677 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -71,7 +71,7 @@ impl Block { } pub fn with_title(mut self, title: &str) -> Self { - self.title = util::optional_str(title); + self.title = util::valid_str(title); self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index c76c49dd..57810fea 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -101,7 +101,7 @@ impl Button { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index ccc6ab31..6614670a 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -112,17 +112,17 @@ impl Date { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::optional_str(label); + self.label = util::valid_str(label); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_str(placeholder); + self.placeholder = util::valid_str(placeholder); self } @@ -167,7 +167,7 @@ impl Date { } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::optional_str(help_text); + self.help_text = util::valid_str(help_text); self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 63eace0c..2fac4403 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -76,7 +76,7 @@ impl Form { } pub fn with_action(mut self, action: &str) -> Self { - self.action = util::optional_str(action); + self.action = util::valid_str(action); self } @@ -86,7 +86,7 @@ impl Form { } pub fn with_charset(mut self, charset: &str) -> Self { - self.charset = util::optional_str(charset); + self.charset = util::valid_str(charset); self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 9ac0a4f9..bd158b85 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -54,7 +54,7 @@ impl Hidden { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 884d2232..f0e73a63 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -167,12 +167,12 @@ impl Input { } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::optional_str(value); + self.value = util::valid_str(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::optional_str(label); + self.label = util::valid_str(label); self } @@ -192,7 +192,7 @@ impl Input { } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::optional_str(placeholder); + self.placeholder = util::valid_str(placeholder); self } @@ -237,7 +237,7 @@ impl Input { } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::optional_str(help_text); + self.help_text = util::valid_str(help_text); self } diff --git a/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl similarity index 95% rename from pagetop/src/base/module/homepage/locales/en-US/homepage.ftl rename to pagetop/src/base/module/demopage/locales/en-US/demopage.ftl index 39a5e426..14c93f2f 100644 --- a/pagetop/src/base/module/homepage/locales/en-US/homepage.ftl +++ b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl @@ -1,5 +1,5 @@ module_fullname = Default homepage -module_description = Displays a default homepage when none is configured. +module_description = Displays a demo homepage when none is configured. page_title = Hello world! diff --git a/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl similarity index 93% rename from pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl rename to pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl index f1d85b2e..39720fcd 100644 --- a/pagetop/src/base/module/homepage/locales/es-ES/homepage.ftl +++ b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl @@ -1,5 +1,5 @@ module_fullname = Página de inicio predeterminada -module_description = Muestra una página de inicio predeterminada cuando no hay ninguna configurada. +module_description = Muestra una página de demostración predeterminada cuando no hay ninguna configurada. page_title = ¡Hola mundo! diff --git a/pagetop/src/base/module/homepage/mod.rs b/pagetop/src/base/module/demopage/mod.rs similarity index 91% rename from pagetop/src/base/module/homepage/mod.rs rename to pagetop/src/base/module/demopage/mod.rs index bd364534..bb6e3b94 100644 --- a/pagetop/src/base/module/homepage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -1,10 +1,14 @@ use crate::prelude::*; -localize!("src/base/module/homepage/locales"); +localize!("src/base/module/demopage/locales"); -pub struct HomepageModule; +pub struct DemopageModule; + +impl ModuleTrait for DemopageModule { + fn name(&self) -> &'static str { + "Demopage" + } -impl ModuleTrait for HomepageModule { fn fullname(&self) -> String { l("module_fullname") } @@ -20,9 +24,13 @@ impl ModuleTrait for HomepageModule { async fn home() -> app::Result { Page::prepare() + .using_theme("Bootsier") .with_title( l("page_title").as_str() ) + + + .add_to("content", Container::prepare() .with_id("welcome") .add(Chunck::markup(html! { diff --git a/pagetop/src/base/module/mod.rs b/pagetop/src/base/module/mod.rs index 070e5b82..7107d180 100644 --- a/pagetop/src/base/module/mod.rs +++ b/pagetop/src/base/module/mod.rs @@ -1 +1 @@ -pub mod homepage; +pub mod demopage; diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index 07b1470f..d4f4f252 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -6,7 +6,7 @@ pub struct AlinerTheme; impl ThemeTrait for AlinerTheme { fn name(&self) -> &'static str { - "aliner" + "Aliner" } fn fullname(&self) -> String { @@ -19,6 +19,10 @@ impl ThemeTrait for AlinerTheme { fn before_render_page(&self, page: &mut Page) { page.assets() + .with_favicon( + Favicon::new() + .with_icon("/theme/favicon.png") + ) .add_stylesheet( StyleSheet::source( "/aliner/css/styles.css" diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index dbd31727..ada65b0e 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -8,7 +8,7 @@ pub struct BootsierTheme; impl ThemeTrait for BootsierTheme { fn name(&self) -> &'static str { - "bootsier" + "Bootsier" } fn fullname(&self) -> String { @@ -23,7 +23,7 @@ impl ThemeTrait for BootsierTheme { page.assets() .with_favicon( Favicon::new() - .with_icon("/bootsier/favicon.png") + .with_icon("/theme/favicon.png") ) .add_stylesheet( StyleSheet::source( diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs index b3a50906..471b3738 100644 --- a/pagetop/src/base/theme/minimal/mod.rs +++ b/pagetop/src/base/theme/minimal/mod.rs @@ -4,7 +4,7 @@ pub struct MinimalTheme; impl ThemeTrait for MinimalTheme { fn name(&self) -> &'static str { - "minimal" + "Minimal" } fn fullname(&self) -> String { diff --git a/pagetop/src/module/all.rs b/pagetop/src/module/all.rs index 120c59b6..c95583e9 100644 --- a/pagetop/src/module/all.rs +++ b/pagetop/src/module/all.rs @@ -10,13 +10,24 @@ static MODULES: Lazy>> = Lazy::new(|| { }); pub fn register_module(module: &'static dyn ModuleTrait) { - let mut modules = MODULES.write().unwrap(); - match modules.iter().find(|m| m.name() == module.name()) { - None => { - trace::info!("{}", module.name()); - modules.push(module); - }, - Some(_) => {}, + let mut list: Vec<&dyn ModuleTrait> = Vec::new(); + add_to(&mut list, module); + list.reverse(); + MODULES.write().unwrap().append(&mut list); +} + +fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { + if !MODULES.read().unwrap().iter().any(|m| m.name() == module.name()) { + if !list.iter().any(|m| m.name() == module.name()) { + trace::debug!("Registering \"{}\" module", module.name()); + list.push(module); + + let mut dependencies = module.dependencies(); + dependencies.reverse(); + for d in dependencies.iter() { + add_to(list, *d); + } + } } } diff --git a/pagetop/src/module/definition.rs b/pagetop/src/module/definition.rs index 9424fbd8..b01f9801 100644 --- a/pagetop/src/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -3,17 +3,9 @@ use crate::app; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; -use std::any::type_name; - /// Los módulos deben implementar este *trait*. pub trait ModuleTrait: Send + Sync { - fn name(&self) -> &'static str { - let name = type_name::(); - match name.rfind("::") { - Some(position) => &name[(position + 2)..], - None => name - } - } + fn name(&self) -> &'static str; fn fullname(&self) -> String; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 58541d22..eff38daa 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -75,7 +75,7 @@ impl<'a> Page<'a> { // Page BUILDER. pub fn with_language(&mut self, language: &str) -> &mut Self { - self.language = util::optional_str(language); + self.language = util::valid_str(language); self } @@ -89,12 +89,12 @@ impl<'a> Page<'a> { } pub fn with_title(&mut self, title: &str) -> &mut Self { - self.title = util::optional_str(title); + self.title = util::valid_str(title); self } pub fn with_description(&mut self, description: &str) -> &mut Self { - self.description = util::optional_str(description); + self.description = util::valid_str(description); self } diff --git a/pagetop/src/theme/all.rs b/pagetop/src/theme/all.rs index cc25d9d8..ee0bfedb 100644 --- a/pagetop/src/theme/all.rs +++ b/pagetop/src/theme/all.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, app, base, theme_static_files, trace}; +use crate::{Lazy, app, theme_static_files, trace}; use super::ThemeTrait; use std::sync::RwLock; @@ -7,21 +7,14 @@ include!(concat!(env!("OUT_DIR"), "/theme.rs")); // Temas registrados. static THEMES: Lazy>> = Lazy::new(|| { - RwLock::new(vec![ - &base::theme::aliner::AlinerTheme, - &base::theme::minimal::MinimalTheme, - &base::theme::bootsier::BootsierTheme, - ]) + RwLock::new(Vec::new()) }); pub fn register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); - match themes.iter().find(|t| t.name() == theme.name()) { - None => { - trace::info!("{}", theme.name()); - themes.push(theme); - }, - Some(_) => {}, + if !themes.iter().any(|t| t.name() == theme.name()) { + trace::debug!("Registering \"{}\" theme", theme.name()); + themes.push(theme); } } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 727df347..733736e2 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,7 +1,7 @@ use crate::app; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::response::page::{Page, PageAssets, PageComponent}; +use crate::response::page::{Favicon, Page, PageAssets, PageComponent}; use crate::base::component::Chunck; /// Los temas deben implementar este "trait". @@ -20,6 +20,11 @@ pub trait ThemeTrait: Send + Sync { #[allow(unused_variables)] fn before_render_page(&self, page: &mut Page) { + page.assets() + .with_favicon( + Favicon::new() + .with_icon("/theme/favicon.png") + ); } fn render_page_head(&self, page: &mut Page) -> Markup { diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index c5254618..4ba4f76e 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -37,24 +37,24 @@ macro_rules! theme_static_files { } pub fn valid_id(id: &str) -> Option { - let id = id.trim().replace(" ", "_").to_lowercase(); + let id = id.trim(); match id.is_empty() { true => None, - false => Some(id), + false => Some(id.replace(" ", "_").to_lowercase()), } } -pub fn optional_str(s: &str) -> Option { - let s = s.to_owned(); +pub fn valid_str(s: &str) -> Option { + let s = s.trim(); match s.is_empty() { true => None, - false => Some(s), + false => Some(s.to_owned()), } } pub fn assigned_str(optional: &Option) -> &str { match optional { Some(o) => o.as_str(), - _ => "", + None => "", } } diff --git a/pagetop/static/theme/favicon.png b/pagetop/static/theme/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7d38ea4a847b5697db4437972cfc28baba5e05e3 GIT binary patch literal 11471 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 Date: Sun, 27 Mar 2022 06:05:37 +0200 Subject: [PATCH 09/80] =?UTF-8?q?A=C3=B1ade=20nuevas=20caracter=C3=ADstica?= =?UTF-8?q?s=20a=20la=20p=C3=A1gina=20demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-admin/src/summary.rs | 22 +- pagetop-node/src/lib.rs | 2 +- pagetop-user/src/lib.rs | 6 +- pagetop/src/base/component/block.rs | 41 +-- pagetop/src/base/component/chunck.rs | 18 +- pagetop/src/base/component/container.rs | 81 ++++-- pagetop/src/base/component/form/button.rs | 73 +++-- pagetop/src/base/component/form/date.rs | 155 +++++------ pagetop/src/base/component/form/form.rs | 32 +-- pagetop/src/base/component/form/hidden.rs | 26 +- pagetop/src/base/component/form/input.rs | 167 ++++++------ pagetop/src/base/component/grid/column.rs | 82 ++++++ pagetop/src/base/component/grid/mod.rs | 4 + pagetop/src/base/component/grid/row.rs | 82 ++++++ pagetop/src/base/component/image.rs | 70 +++++ pagetop/src/base/component/menu.rs | 24 +- pagetop/src/base/component/mod.rs | 5 + .../demopage/locales/en-US/demopage.ftl | 28 +- .../demopage/locales/es-ES/demopage.ftl | 28 +- pagetop/src/base/module/demopage/mod.rs | 253 ++++++++++++++---- pagetop/src/base/theme/bootsier/mod.rs | 4 +- pagetop/src/html.rs | 1 - pagetop/src/html/classes.rs | 63 +++++ pagetop/src/html/mod.rs | 8 + pagetop/src/html/optional_attr.rs | 41 +++ pagetop/src/html/optional_id.rs | 33 +++ pagetop/src/response/page/component.rs | 2 +- pagetop/src/response/page/page.rs | 76 +++--- pagetop/src/theme/definition.rs | 4 +- pagetop/src/util.rs | 23 -- .../static/bootsier/images/demo-header.svg | 1 + .../static/bootsier/images/demo-pagetop.svg | 1 + .../static/bootsier/images/demo-visiting.svg | 1 + 33 files changed, 987 insertions(+), 470 deletions(-) create mode 100644 pagetop/src/base/component/grid/column.rs create mode 100644 pagetop/src/base/component/grid/mod.rs create mode 100644 pagetop/src/base/component/grid/row.rs create mode 100644 pagetop/src/base/component/image.rs delete mode 100644 pagetop/src/html.rs create mode 100644 pagetop/src/html/classes.rs create mode 100644 pagetop/src/html/mod.rs create mode 100644 pagetop/src/html/optional_attr.rs create mode 100644 pagetop/src/html/optional_id.rs create mode 100644 pagetop/static/bootsier/images/demo-header.svg create mode 100644 pagetop/static/bootsier/images/demo-pagetop.svg create mode 100644 pagetop/static/bootsier/images/demo-visiting.svg diff --git a/pagetop-admin/src/summary.rs b/pagetop-admin/src/summary.rs index 79bf426e..b91b97fa 100644 --- a/pagetop-admin/src/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -2,37 +2,37 @@ use pagetop::prelude::*; use super::l; pub async fn summary() -> app::Result { - let top_menu = Menu::prepare() + let top_menu = Menu::new() .add(MenuItem::label(l("module_fullname").as_str())) .add(MenuItem::link("Opción 2", "https://www.google.es")) .add(MenuItem::link_blank("Opción 3", "https://www.google.es")) - .add(MenuItem::submenu("Submenú 1", Menu::prepare() + .add(MenuItem::submenu("Submenú 1", Menu::new() .add(MenuItem::label("Opción 1")) .add(MenuItem::label("Opción 2")) )) .add(MenuItem::separator()) - .add(MenuItem::submenu("Submenú 2", Menu::prepare() + .add(MenuItem::submenu("Submenú 2", Menu::new() .add(MenuItem::label("Opción 1")) .add(MenuItem::label("Opción 2")) )) .add(MenuItem::label("Opción 4")); - let side_menu = Menu::prepare() + let side_menu = Menu::new() .add(MenuItem::label("Opción 1")) .add(MenuItem::link("Opción 2", "https://www.google.es")) .add(MenuItem::link_blank("Opción 3", "https://www.google.es")) - .add(MenuItem::submenu("Submenú 1", Menu::prepare() + .add(MenuItem::submenu("Submenú 1", Menu::new() .add(MenuItem::label("Opción 1")) .add(MenuItem::label("Opción 2")) )) .add(MenuItem::separator()) - .add(MenuItem::submenu("Submenú 2", Menu::prepare() + .add(MenuItem::submenu("Submenú 2", Menu::new() .add(MenuItem::label("Opción 1")) .add(MenuItem::label("Opción 2")) )) .add(MenuItem::label("Opción 4")); - Page::prepare() + Page::new() .using_theme("bootsier") @@ -40,12 +40,12 @@ pub async fn summary() -> app::Result { .add_to("top-menu", top_menu) - .add_to("content", Container::row() - .add(Container::column() + .add_to("content", grid::Row::new() + .add_column(grid::Column::new() .add(side_menu) ) - .add(Container::column() - .add(Chunck::markup(html! { + .add_column(grid::Column::new() + .add(Chunck::with(html! { p { "Columna 2"} })) ) diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index afcd729f..0f5c4662 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -35,7 +35,7 @@ impl ModuleTrait for NodeModule { } async fn node() -> app::Result { - Page::prepare() + Page::new() .with_title( "Nodo" ) diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 343daa7a..7ef2ecf3 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -32,7 +32,7 @@ impl ModuleTrait for UserModule { } fn form_login() -> impl PageComponent { - Form::prepare() + Form::new() .with_id("user-login") .add(form::Input::textfield() .with_name("name") @@ -51,11 +51,11 @@ fn form_login() -> impl PageComponent { } async fn login() -> app::Result { - Page::prepare() + Page::new() .with_title( "Identificación del usuario" ) - .add_to("content", Container::prepare() + .add_to("content", Container::new() .with_id("welcome") .add(form_login()) ) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 96fce677..b857712f 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -3,21 +3,21 @@ use crate::prelude::*; pub struct Block { renderable: fn() -> bool, weight : i8, - id : Option, - title : Option, - markup : Vec, + id : OptionId, + title : OptionAttr, + html : Vec, template : String, } impl PageComponent for Block { - fn prepare() -> Self { + fn new() -> Self { Block { renderable: always, weight : 0, - id : None, - title : None, - markup : Vec::new(), + id : OptionId::none(), + title : OptionAttr::none(), + html : Vec::new(), template : "default".to_owned(), } } @@ -31,15 +31,16 @@ impl PageComponent for Block { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let id = assets.serial_id(self.name(), self.id()); + let id = assets.serial_id(self.name(), self.id.value()); + let title = self.title.value(); html! { div id=(id) class="block" { - @if self.title != None { - h2 class="block-title" { (self.title()) } + @if !title.is_empty() { + h2 class="block-title" { (title) } } div class="block-body" { - @for markup in self.markup.iter() { - (*markup) + @for html in self.html.iter() { + (*html) } } } @@ -49,8 +50,8 @@ impl PageComponent for Block { impl Block { - pub fn markup(markup: Markup) -> Self { - Block::prepare().add_markup(markup) + pub fn with(html: Markup) -> Self { + Block::new().add(html) } // Block BUILDER. @@ -66,17 +67,17 @@ impl Block { } pub fn with_id(mut self, id: &str) -> Self { - self.id = util::valid_id(id); + self.id.with_value(id); self } pub fn with_title(mut self, title: &str) -> Self { - self.title = util::valid_str(title); + self.title.with_value(title); self } - pub fn add_markup(mut self, markup: Markup) -> Self { - self.markup.push(markup); + pub fn add(mut self, html: Markup) -> Self { + self.html.push(html); self } @@ -88,11 +89,11 @@ impl Block { // Block GETTERS. pub fn id(&self) -> &str { - util::assigned_str(&self.id) + self.id.value() } pub fn title(&self) -> &str { - util::assigned_str(&self.title) + self.title.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 63cc20f7..b03ac0c8 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -3,17 +3,17 @@ use crate::prelude::*; pub struct Chunck { renderable: fn() -> bool, weight : i8, - markup : Vec, + html : Vec, template : String, } impl PageComponent for Chunck { - fn prepare() -> Self { + fn new() -> Self { Chunck { renderable: always, weight : 0, - markup : Vec::new(), + html : Vec::new(), template : "default".to_owned(), } } @@ -28,8 +28,8 @@ impl PageComponent for Chunck { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - @for markup in self.markup.iter() { - (*markup) + @for html in self.html.iter() { + (*html) } } } @@ -37,8 +37,8 @@ impl PageComponent for Chunck { impl Chunck { - pub fn markup(markup: Markup) -> Self { - Chunck::prepare().add_markup(markup) + pub fn with(html: Markup) -> Self { + Chunck::new().add(html) } // Chunck BUILDER. @@ -53,8 +53,8 @@ impl Chunck { self } - pub fn add_markup(mut self, markup: Markup) -> Self { - self.markup.push(markup); + pub fn add(mut self, html: Markup) -> Self { + self.html.push(html); self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 161bea78..18d6337a 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -1,11 +1,11 @@ use crate::prelude::*; -enum ContainerType { Column, Row, Wrapper } +enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable: fn() -> bool, weight : i8, - id : Option, + id : OptionId, container : ContainerType, components: PageContainer, template : String, @@ -13,11 +13,11 @@ pub struct Container { impl PageComponent for Container { - fn prepare() -> Self { + fn new() -> Self { Container { renderable: always, weight : 0, - id : None, + id : OptionId::none(), container : ContainerType::Wrapper, components: PageContainer::new(), template : "default".to_owned(), @@ -33,14 +33,39 @@ impl PageComponent for Container { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let classes = match self.container { - ContainerType::Wrapper => "container", - ContainerType::Row => "row", - ContainerType::Column => "col", - }; - html! { - div id=[&self.id] class=(classes) { - (self.components.render(assets)) + match self.container { + ContainerType::Header => html! { + header id=[&self.id.option()] class="header" { + div class="container" { + (self.components.render(assets)) + } + } + }, + ContainerType::Footer => html! { + footer id=[&self.id.option()] class="footer" { + div class="container" { + (self.components.render(assets)) + } + } + }, + ContainerType::Main => html! { + main id=[&self.id.option()] class="main" { + div class="container" { + (self.components.render(assets)) + } + } + }, + ContainerType::Section => html! { + section id=[&self.id.option()] class="section" { + div class="container" { + (self.components.render(assets)) + } + } + }, + _ => html! { + div id=[&self.id.option()] class="container" { + (self.components.render(assets)) + } } } } @@ -48,16 +73,28 @@ impl PageComponent for Container { impl Container { - pub fn row() -> Self { - let mut grid = Container::prepare(); - grid.container = ContainerType::Row; - grid + pub fn header() -> Self { + let mut c = Container::new(); + c.container = ContainerType::Header; + c } - pub fn column() -> Self { - let mut grid = Container::prepare(); - grid.container = ContainerType::Column; - grid + pub fn footer() -> Self { + let mut c = Container::new(); + c.container = ContainerType::Footer; + c + } + + pub fn main() -> Self { + let mut c = Container::new(); + c.container = ContainerType::Main; + c + } + + pub fn section() -> Self { + let mut c = Container::new(); + c.container = ContainerType::Section; + c } // Container BUILDER. @@ -73,7 +110,7 @@ impl Container { } pub fn with_id(mut self, id: &str) -> Self { - self.id = util::valid_id(id); + self.id.with_value(id); self } @@ -90,7 +127,7 @@ impl Container { // Container GETTERS. pub fn id(&self) -> &str { - util::assigned_str(&self.id) + self.id.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 57810fea..a1975ea4 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -6,24 +6,24 @@ pub struct Button { renderable : fn() -> bool, weight : i8, button_type: ButtonType, - name : Option, - value : Option, - autofocus : Option, - disabled : Option, + name : OptionAttr, + value : OptionAttr, + autofocus : OptionAttr, + disabled : OptionAttr, template : String, } impl PageComponent for Button { - fn prepare() -> Self { + fn new() -> Self { Button { renderable : always, weight : 0, button_type: ButtonType::Button, - name : None, - value : None, - autofocus : None, - disabled : None, + name : OptionAttr::none(), + value : OptionAttr::none(), + autofocus : OptionAttr::none(), + disabled : OptionAttr::none(), template : "default".to_owned(), } } @@ -42,7 +42,7 @@ impl PageComponent for Button { ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), ButtonType::Submit => ("submit", "btn btn-primary form-submit") }; - let id_item = match &self.name { + let id_item = match &self.name.option() { Some(name) => Some(format!("edit-{}", name)), _ => None }; @@ -51,15 +51,12 @@ impl PageComponent for Button { type=(button_type) id=[&id_item] class=(button_class) - name=[&self.name] - value=[&self.value] - autofocus=[&self.autofocus] - disabled=[&self.disabled] + name=[&self.name.option()] + value=[&self.value.option()] + autofocus=[&self.autofocus.option()] + disabled=[&self.disabled.option()] { - @match &self.value { - Some(value) => (value), - _ => "" - }; + (self.value.value()) } } } @@ -68,17 +65,17 @@ impl PageComponent for Button { impl Button { pub fn button(value: &str) -> Self { - Button::prepare().with_value(value) + Button::new().with_value(value) } pub fn reset(value: &str) -> Self { - let mut button = Button::prepare().with_value(value); + let mut button = Button::new().with_value(value); button.button_type = ButtonType::Reset; button } pub fn submit(value: &str) -> Self { - let mut button = Button::prepare().with_value(value); + let mut button = Button::new().with_value(value); button.button_type = ButtonType::Submit; button } @@ -96,28 +93,28 @@ impl Button { } pub fn with_name(mut self, name: &str) -> Self { - self.name = util::valid_id(name); + self.name.with_value(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::valid_str(value); + self.value.with_value(value); self } pub fn autofocus(mut self, toggle: bool) -> Self { - self.autofocus = match toggle { - true => Some("autofocus".to_owned()), - false => None - }; + self.autofocus.with_value(match toggle { + true => "autofocus", + false => "", + }); self } pub fn disabled(mut self, toggle: bool) -> Self { - self.disabled = match toggle { - true => Some("disabled".to_owned()), - false => None - }; + self.disabled.with_value(match toggle { + true => "disabled", + false => "", + }); self } @@ -129,25 +126,19 @@ impl Button { // Button GETTERS. pub fn name(&self) -> &str { - util::assigned_str(&self.name) + self.name.value() } pub fn value(&self) -> &str { - util::assigned_str(&self.value) + self.value.value() } pub fn has_autofocus(&self) -> bool { - match &self.autofocus { - Some(_) => true, - _ => false - } + self.autofocus.has_value() } pub fn is_disabled(&self) -> bool { - match &self.disabled { - Some(_) => true, - _ => false - } + self.disabled.has_value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 6614670a..7f04691b 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -3,35 +3,35 @@ use crate::prelude::*; pub struct Date { renderable : fn() -> bool, weight : i8, - name : Option, - value : Option, - label : Option, - placeholder : Option, - autofocus : Option, - autocomplete: Option, - disabled : Option, - readonly : Option, - required : Option, - help_text : Option, + name : OptionAttr, + value : OptionAttr, + label : OptionAttr, + placeholder : OptionAttr, + autofocus : OptionAttr, + autocomplete: OptionAttr, + disabled : OptionAttr, + readonly : OptionAttr, + required : OptionAttr, + help_text : OptionAttr, template : String, } impl PageComponent for Date { - fn prepare() -> Self { + fn new() -> Self { Date { renderable : always, weight : 0, - name : None, - value : None, - label : None, - placeholder : None, - autofocus : None, - autocomplete: None, - disabled : None, - readonly : None, - required : None, - help_text : None, + name : OptionAttr::none(), + value : OptionAttr::none(), + label : OptionAttr::none(), + placeholder : OptionAttr::none(), + autofocus : OptionAttr::none(), + autocomplete: OptionAttr::none(), + disabled : OptionAttr::none(), + readonly : OptionAttr::none(), + required : OptionAttr::none(), + help_text : OptionAttr::none(), template : "default".to_owned(), } } @@ -45,7 +45,7 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (class_item, id_item) = match &self.name { + let (class_item, id_item) = match self.name.option() { Some(name) => ( format!("form-item form-item-{} form-type-date", name), Some(format!("edit-{}", name)) @@ -57,10 +57,10 @@ impl PageComponent for Date { }; html! { div class=(class_item) { - @if self.label != None { + @if self.label.has_value() { label class="form-label" for=[&id_item] { - (self.label()) " " - @if self.required != None { + (self.label.value()) " " + @if self.required.has_value() { span class="form-required" title="Este campo es obligatorio." @@ -74,17 +74,17 @@ impl PageComponent for Date { type="date" id=[&id_item] class="form-control" - name=[&self.name] - value=[&self.value] - placeholder=[&self.placeholder] - autofocus=[&self.autofocus] - autocomplete=[&self.autocomplete] - readonly=[&self.readonly] - required=[&self.required] - disabled=[&self.disabled]; - @if self.help_text != None { + name=[&self.name.option()] + value=[&self.value.option()] + placeholder=[&self.placeholder.option()] + autofocus=[&self.autofocus.option()] + autocomplete=[&self.autocomplete.option()] + readonly=[&self.readonly.option()] + required=[&self.required.option()] + disabled=[&self.disabled.option()]; + @if self.help_text.has_value() { div class="form-text" { - (self.help_text()) + (self.help_text.value()) } } } @@ -107,67 +107,67 @@ impl Date { } pub fn with_name(mut self, name: &str) -> Self { - self.name = util::valid_id(name); + self.name.with_value(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::valid_str(value); + self.value.with_value(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::valid_str(label); + self.label.with_value(label); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::valid_str(placeholder); + self.placeholder.with_value(placeholder); self } pub fn autofocus(mut self, toggle: bool) -> Self { - self.autofocus = match toggle { - true => Some("autofocus".to_owned()), - false => None - }; + self.autofocus.with_value(match toggle { + true => "autofocus", + false => "", + }); self } pub fn autocomplete(mut self, toggle: bool) -> Self { - self.autocomplete = match toggle { - true => None, - false => Some("off".to_owned()) - }; + self.autocomplete.with_value(match toggle { + true => "", + false => "off", + }); self } pub fn disabled(mut self, toggle: bool) -> Self { - self.disabled = match toggle { - true => Some("disabled".to_owned()), - false => None - }; + self.disabled.with_value(match toggle { + true => "disabled", + false => "", + }); self } pub fn readonly(mut self, toggle: bool) -> Self { - self.readonly = match toggle { - true => Some("readonly".to_owned()), - false => None - }; + self.readonly.with_value(match toggle { + true => "readonly", + false => "", + }); self } pub fn required(mut self, toggle: bool) -> Self { - self.required = match toggle { - true => Some("required".to_owned()), - false => None - }; + self.required.with_value(match toggle { + true => "required", + false => "", + }); self } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::valid_str(help_text); + self.help_text.with_value(help_text); self } @@ -179,58 +179,43 @@ impl Date { // Date GETTERS. pub fn name(&self) -> &str { - util::assigned_str(&self.name) + self.name.value() } pub fn value(&self) -> &str { - util::assigned_str(&self.value) + self.value.value() } pub fn label(&self) -> &str { - util::assigned_str(&self.label) + self.label.value() } pub fn placeholder(&self) -> &str { - util::assigned_str(&self.placeholder) + self.placeholder.value() } pub fn has_autofocus(&self) -> bool { - match &self.autofocus { - Some(_) => true, - _ => false - } + self.autofocus.has_value() } pub fn has_autocomplete(&self) -> bool { - match &self.autocomplete { - Some(_) => false, - _ => true - } + !self.autocomplete.has_value() } pub fn is_disabled(&self) -> bool { - match &self.disabled { - Some(_) => true, - _ => false - } + self.disabled.has_value() } pub fn is_readonly(&self) -> bool { - match &self.readonly { - Some(_) => true, - _ => false - } + self.readonly.has_value() } pub fn is_required(&self) -> bool { - match &self.required { - Some(_) => true, - _ => false - } + self.required.has_value() } pub fn help_text(&self) -> &str { - util::assigned_str(&self.help_text) + self.help_text.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 2fac4403..e93926a7 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -5,24 +5,24 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : i8, - id : Option, - action : Option, + id : OptionId, + action : OptionAttr, method : FormMethod, - charset : Option, + charset : OptionAttr, elements : PageContainer, template : String, } impl PageComponent for Form { - fn prepare() -> Self { + fn new() -> Self { Form { renderable: always, weight : 0, - id : None, - action : None, + id : OptionId::none(), + action : OptionAttr::none(), method : FormMethod::Post, - charset : Some("UTF-8".to_owned()), + charset : OptionAttr::some("UTF-8"), elements : PageContainer::new(), template : "default".to_owned(), } @@ -43,10 +43,10 @@ impl PageComponent for Form { }; html! { form - id=[&self.id] - action=[&self.action] + id=[&self.id.option()] + action=[&self.action.option()] method=[method] - accept-charset=[&self.charset] + accept-charset=[&self.charset.option()] { div { (self.elements.render(assets)) @@ -71,12 +71,12 @@ impl Form { } pub fn with_id(mut self, id: &str) -> Self { - self.id = util::valid_id(id); + self.id.with_value(id); self } pub fn with_action(mut self, action: &str) -> Self { - self.action = util::valid_str(action); + self.action.with_value(action); self } @@ -86,7 +86,7 @@ impl Form { } pub fn with_charset(mut self, charset: &str) -> Self { - self.charset = util::valid_str(charset); + self.charset.with_value(charset); self } @@ -103,11 +103,11 @@ impl Form { // Form GETTERS. pub fn id(&self) -> &str { - util::assigned_str(&self.id) + self.id.value() } pub fn action(&self) -> &str { - util::assigned_str(&self.action) + self.action.value() } pub fn method(&self) -> &str { @@ -118,7 +118,7 @@ impl Form { } pub fn charset(&self) -> &str { - util::assigned_str(&self.charset) + self.charset.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index bd158b85..b27caf37 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -2,17 +2,17 @@ use crate::prelude::*; pub struct Hidden { weight : i8, - name : Option, - value : Option, + name : OptionId, + value : OptionAttr, } impl PageComponent for Hidden { - fn prepare() -> Self { + fn new() -> Self { Hidden { weight : 0, - name : None, - value : None, + name : OptionId::none(), + value : OptionAttr::none(), } } @@ -21,7 +21,7 @@ impl PageComponent for Hidden { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let id_item = match &self.name { + let id_item = match self.name.option() { Some(name) => Some(format!("value-{}", name)), _ => None }; @@ -29,8 +29,8 @@ impl PageComponent for Hidden { input type="hidden" id=[&id_item] - name=[&self.name] - value=[&self.value]; + name=[&self.name.option()] + value=[&self.value.option()]; } } } @@ -38,7 +38,7 @@ impl PageComponent for Hidden { impl Hidden { pub fn set(name: &str, value: &str) -> Self { - Hidden::prepare().with_name(name).with_value(value) + Hidden::new().with_name(name).with_value(value) } // Hidden BUILDER. @@ -49,22 +49,22 @@ impl Hidden { } pub fn with_name(mut self, name: &str) -> Self { - self.name = util::valid_id(name); + self.name.with_value(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::valid_str(value); + self.value.with_value(value); self } // Hidden GETTERS. pub fn name(&self) -> &str { - util::assigned_str(&self.name) + self.name.value() } pub fn value(&self) -> &str { - util::assigned_str(&self.value) + self.value.value() } } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index f0e73a63..c483c9a9 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -6,42 +6,42 @@ pub struct Input { renderable : fn() -> bool, weight : i8, input_type : InputType, - name : Option, - value : Option, - label : Option, + name : OptionId, + value : OptionAttr, + label : OptionAttr, size : Option, minlength : Option, maxlength : Option, - placeholder : Option, - autofocus : Option, - autocomplete: Option, - disabled : Option, - readonly : Option, - required : Option, - help_text : Option, + placeholder : OptionAttr, + autofocus : OptionAttr, + autocomplete: OptionAttr, + disabled : OptionAttr, + readonly : OptionAttr, + required : OptionAttr, + help_text : OptionAttr, template : String, } impl PageComponent for Input { - fn prepare() -> Self { + fn new() -> Self { Input { renderable : always, weight : 0, input_type : InputType::Textfield, - name : None, - value : None, - label : None, + name : OptionId::none(), + value : OptionAttr::none(), + label : OptionAttr::none(), size : Some(60), minlength : None, maxlength : Some(128), - placeholder : None, - autofocus : None, - autocomplete: None, - disabled : None, - readonly : None, - required : None, - help_text : None, + placeholder : OptionAttr::none(), + autofocus : OptionAttr::none(), + autocomplete: OptionAttr::none(), + disabled : OptionAttr::none(), + readonly : OptionAttr::none(), + required : OptionAttr::none(), + help_text : OptionAttr::none(), template : "default".to_owned(), } } @@ -63,7 +63,7 @@ impl PageComponent for Input { InputType::Textfield => ("text", "form-type-textfield"), InputType::Url => ("url", "form-type-url") }; - let (class_item, id_item) = match &self.name { + let (class_item, id_item) = match &self.name.option() { Some(name) => ( format!("form-item form-item-{} {}", name, class_type), Some(format!("edit-{}", name)) @@ -75,10 +75,10 @@ impl PageComponent for Input { }; html! { div class=(class_item) { - @if self.label != None { + @if self.label.has_value() { label class="form-label" for=[&id_item] { - (self.label()) " " - @if self.required != None { + (self.label.value()) " " + @if self.required.has_value() { span class="form-required" title="Este campo es obligatorio." @@ -92,20 +92,20 @@ impl PageComponent for Input { type=(input_type) id=[&id_item] class="form-control" - name=[&self.name] - value=[&self.value] + name=[&self.name.option()] + value=[&self.value.option()] size=[self.size] minlength=[self.minlength] maxlength=[self.maxlength] - placeholder=[&self.placeholder] - autofocus=[&self.autofocus] - autocomplete=[&self.autocomplete] - readonly=[&self.readonly] - required=[&self.required] - disabled=[&self.disabled]; - @if self.help_text != None { + placeholder=[&self.placeholder.option()] + autofocus=[&self.autofocus.option()] + autocomplete=[&self.autocomplete.option()] + readonly=[&self.readonly.option()] + required=[&self.required.option()] + disabled=[&self.disabled.option()]; + @if self.help_text.has_value() { div class="form-text" { - (self.help_text()) + (self.help_text.value()) } } } @@ -116,35 +116,35 @@ impl PageComponent for Input { impl Input { pub fn textfield() -> Self { - Input::prepare() + Input::new() } pub fn password() -> Self { - let mut input = Input::prepare(); + let mut input = Input::new(); input.input_type = InputType::Password; input } pub fn search() -> Self { - let mut input = Input::prepare(); + let mut input = Input::new(); input.input_type = InputType::Search; input } pub fn email() -> Self { - let mut input = Input::prepare(); + let mut input = Input::new(); input.input_type = InputType::Email; input } pub fn telephone() -> Self { - let mut input = Input::prepare(); + let mut input = Input::new(); input.input_type = InputType::Telephone; input } pub fn url() -> Self { - let mut input = Input::prepare(); + let mut input = Input::new(); input.input_type = InputType::Url; input } @@ -162,17 +162,17 @@ impl Input { } pub fn with_name(mut self, name: &str) -> Self { - self.name = util::valid_id(name); + self.name.with_value(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value = util::valid_str(value); + self.value.with_value(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label = util::valid_str(label); + self.label.with_value(label); self } @@ -192,52 +192,52 @@ impl Input { } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder = util::valid_str(placeholder); + self.placeholder.with_value(placeholder); self } pub fn autofocus(mut self, toggle: bool) -> Self { - self.autofocus = match toggle { - true => Some("autofocus".to_owned()), - false => None - }; + self.autofocus.with_value(match toggle { + true => "autofocus", + false => "", + }); self } pub fn autocomplete(mut self, toggle: bool) -> Self { - self.autocomplete = match toggle { - true => None, - false => Some("off".to_owned()) - }; + self.autocomplete.with_value(match toggle { + true => "", + false => "off", + }); self } pub fn disabled(mut self, toggle: bool) -> Self { - self.disabled = match toggle { - true => Some("disabled".to_owned()), - false => None - }; + self.disabled.with_value(match toggle { + true => "disabled", + false => "", + }); self } pub fn readonly(mut self, toggle: bool) -> Self { - self.readonly = match toggle { - true => Some("readonly".to_owned()), - false => None - }; + self.readonly.with_value(match toggle { + true => "readonly", + false => "", + }); self } pub fn required(mut self, toggle: bool) -> Self { - self.required = match toggle { - true => Some("required".to_owned()), - false => None - }; + self.required.with_value(match toggle { + true => "required", + false => "", + }); self } pub fn with_help_text(mut self, help_text: &str) -> Self { - self.help_text = util::valid_str(help_text); + self.help_text.with_value(help_text); self } @@ -249,15 +249,15 @@ impl Input { // Input GETTERS. pub fn name(&self) -> &str { - util::assigned_str(&self.name) + self.name.value() } pub fn value(&self) -> &str { - util::assigned_str(&self.value) + self.value.value() } pub fn label(&self) -> &str { - util::assigned_str(&self.label) + self.label.value() } pub fn size(&self) -> Option { @@ -273,46 +273,31 @@ impl Input { } pub fn placeholder(&self) -> &str { - util::assigned_str(&self.placeholder) + self.placeholder.value() } pub fn has_autofocus(&self) -> bool { - match &self.autofocus { - Some(_) => true, - _ => false - } + self.autofocus.has_value() } pub fn has_autocomplete(&self) -> bool { - match &self.autocomplete { - Some(_) => false, - _ => true - } + !self.autocomplete.has_value() } pub fn is_disabled(&self) -> bool { - match &self.disabled { - Some(_) => true, - _ => false - } + self.disabled.has_value() } pub fn is_readonly(&self) -> bool { - match &self.readonly { - Some(_) => true, - _ => false - } + self.readonly.has_value() } pub fn is_required(&self) -> bool { - match &self.required { - Some(_) => true, - _ => false - } + self.required.has_value() } pub fn help_text(&self) -> &str { - util::assigned_str(&self.help_text) + self.help_text.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs new file mode 100644 index 00000000..96463490 --- /dev/null +++ b/pagetop/src/base/component/grid/column.rs @@ -0,0 +1,82 @@ +use crate::prelude::*; + +pub struct Column { + renderable: fn() -> bool, + weight : i8, + id : OptionId, + components: PageContainer, + template : String, +} + +impl PageComponent for Column { + + fn new() -> Self { + Column { + renderable: always, + weight : 0, + id : OptionId::none(), + components: PageContainer::new(), + template : "default".to_owned(), + } + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> i8 { + self.weight + } + + fn default_render(&self, assets: &mut PageAssets) -> Markup { + html! { + div id=[&self.id.option()] class="col" { + (self.components.render(assets)) + } + } + } +} + +impl Column { + + // Column BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn with_id(mut self, id: &str) -> Self { + self.id.with_value(id); + self + } + + pub fn add(mut self, component: impl PageComponent) -> Self { + self.components.add(component); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.template = template.to_owned(); + self + } + + // Column GETTERS. + + pub fn id(&self) -> &str { + self.id.value() + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} + +fn always() -> bool { + true +} diff --git a/pagetop/src/base/component/grid/mod.rs b/pagetop/src/base/component/grid/mod.rs new file mode 100644 index 00000000..ca7796ef --- /dev/null +++ b/pagetop/src/base/component/grid/mod.rs @@ -0,0 +1,4 @@ +mod row; +pub use row::Row; +mod column; +pub use column::Column; diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs new file mode 100644 index 00000000..6aed7d0f --- /dev/null +++ b/pagetop/src/base/component/grid/row.rs @@ -0,0 +1,82 @@ +use crate::prelude::*; + +pub struct Row { + renderable: fn() -> bool, + weight : i8, + id : OptionId, + columns : PageContainer, + template : String, +} + +impl PageComponent for Row { + + fn new() -> Self { + Row { + renderable: always, + weight : 0, + id : OptionId::none(), + columns : PageContainer::new(), + template : "default".to_owned(), + } + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> i8 { + self.weight + } + + fn default_render(&self, assets: &mut PageAssets) -> Markup { + html! { + div id=[&self.id.option()] class="row" { + (self.columns.render(assets)) + } + } + } +} + +impl Row { + + // Row BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn with_id(mut self, id: &str) -> Self { + self.id.with_value(id); + self + } + + pub fn add_column(mut self, column: grid::Column) -> Self { + self.columns.add(column); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.template = template.to_owned(); + self + } + + // Row GETTERS. + + pub fn id(&self) -> &str { + self.id.value() + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} + +fn always() -> bool { + true +} diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs new file mode 100644 index 00000000..b330b374 --- /dev/null +++ b/pagetop/src/base/component/image.rs @@ -0,0 +1,70 @@ +use crate::prelude::*; + +pub struct Image { + renderable: fn() -> bool, + weight : i8, + source : Option, + template : String, +} + +impl PageComponent for Image { + + fn new() -> Self { + Image { + renderable: always, + weight : 0, + source : None, + template : "default".to_owned(), + } + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> i8 { + self.weight + } + + fn default_render(&self, _: &mut PageAssets) -> Markup { + html! { + img src=[&self.source] class="img-fluid" {} + } + } +} + +impl Image { + + pub fn image(source: &str) -> Self { + let mut i = Image::new(); + i.source = Some(source.to_owned()); + i + } + + // Image BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.template = template.to_owned(); + self + } + + // Image GETTERS. + + pub fn template(&self) -> &str { + self.template.as_str() + } +} + +fn always() -> bool { + true +} diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index d3cdb6b8..10ac8ca5 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -4,7 +4,7 @@ enum MenuItemType { Label(String), Link(String, String), LinkBlank(String, String), - Markup(Markup), + Html(Markup), Separator, Submenu(String, Menu), } @@ -21,7 +21,7 @@ pub struct MenuItem { impl PageComponent for MenuItem { - fn prepare() -> Self { + fn new() -> Self { MenuItem { renderable: always, weight : 0, @@ -50,8 +50,8 @@ impl PageComponent for MenuItem { a href=(path) target="_blank" { (label) } } }, - Some(MenuItemType::Markup(markup)) => html! { - li class="markup" { (*markup) } + Some(MenuItemType::Html(html)) => html! { + li class="html" { (*html) } }, Some(MenuItemType::Submenu(label, menu)) => html! { li class="submenu" { @@ -101,11 +101,11 @@ impl MenuItem { } } - pub fn markup(markup: Markup) -> Self { + pub fn html(html: Markup) -> Self { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Markup(markup)), + item_type : Some(MenuItemType::Html(html)), } } @@ -148,18 +148,18 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, weight : i8, - id : Option, + id : OptionId, items : PageContainer, template : String, } impl PageComponent for Menu { - fn prepare() -> Self { + fn new() -> Self { Menu { renderable: always, weight : 0, - id : None, + id : OptionId::none(), items : PageContainer::new(), template : "default".to_owned(), } @@ -186,7 +186,7 @@ impl PageComponent for Menu { )) .add_jquery(); - let id = assets.serial_id(self.name(), self.id()); + let id = assets.serial_id(self.name(), self.id.value()); html! { ul id=(id) class="sm sm-clean" { (self.render_items(assets)) @@ -216,7 +216,7 @@ impl Menu { } pub fn with_id(mut self, id: &str) -> Self { - self.id = util::valid_id(id); + self.id.with_value(id); self } @@ -233,7 +233,7 @@ impl Menu { // Menu GETTERS. pub fn id(&self) -> &str { - util::assigned_str(&self.id) + self.id.value() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index f9973108..4619c937 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -1,9 +1,14 @@ mod container; pub use container::Container; + +pub mod grid; + mod chunck; pub use chunck::Chunck; mod block; pub use block::Block; +mod image; +pub use image::Image; mod menu; pub use menu::{Menu, MenuItem}; diff --git a/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl index 14c93f2f..d23f6ce6 100644 --- a/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl +++ b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl @@ -3,19 +3,23 @@ module_description = Displays a demo homepage when none is configured. page_title = Hello world! -text_welcome = This page is used to test the proper operation of { $app } after installation. This web solution is powered by { $pagetop }. If you can read this page, it means that the PageTop server is working properly, but has not yet been configured. +welcome_to = Welcome to { $app } +welcome_intro = This page is used to test the proper operation of { $app } after installation. +welcome_pagetop = This web solution is powered by { $pagetop }. -title_normal_user = Just visiting? -text1_normal_user = If you are a normal user of this web site and don't know what this page is about, this probably means that the site is either experiencing problems or is undergoing routine maintenance. -text2_normal_user = If the problem persists, please contact your system administrator. +visiting_title = Just visiting? +visiting_subtitle = Are you user of this website? +visiting_text1 = If you don't know what this page is about, this probably means that the site is either experiencing problems or is undergoing routine maintenance. +visiting_text2 = If the problem persists, please contact your system administrator. -title_about_pagetop = About PageTop -text1_about_pagetop = PageTop defines an interface for the most stable and popular Rust packages to build modular, extensible and configurable web solutions. -text2_about_pagetop = For information on PageTop please visit the "PageTop website". +pagetop_title = About PageTop +pagetop_text1 = If you can read this page, it means that the PageTop server is working properly, but has not yet been configured. +pagetop_text2 = PageTop defines an interface for the most stable and popular Rust packages to build modular, extensible and configurable web solutions. +pagetop_text3 = For information on PageTop please visit the "PageTop website". -title_promo_pagetop = Promoting PageTop -text1_promo_pagetop = You are free to use the image below on applications powered by { $pagetop }. Thanks for using PageTop! +pagetop_promo_title = Promoting PageTop +pagetop_promo_text1 = You are free to use the image below on applications powered by { $pagetop }. Thanks for using PageTop! -title_report_problems = Reporting Problems -text1_report_problems = Please use the GitLab tool to report bugs in PageTop. However, check "existing bug reports" before reporting a new bug. -text2_report_problems = Please report bugs specific to modules (such as admin, and others) to respective packages, not to PageTop itself. +report_problems_title = Reporting Problems +report_problems_text1 = Please use the GitLab tool to report bugs in PageTop. However, check "existing bug reports" before reporting a new bug. +report_problems_text2 = Please report bugs specific to modules (such as admin, and others) to respective packages, not to PageTop itself. diff --git a/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl index 39720fcd..70706ca8 100644 --- a/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl +++ b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl @@ -3,19 +3,23 @@ module_description = Muestra una página de demostración predeterminada cuando page_title = ¡Hola mundo! -text_welcome = Esta página se utiliza para probar el correcto funcionamiento de { $app } después de la instalación. Esta solución web funciona con { $pagetop }. Si puede leer esta página, significa que el servidor PageTop funciona correctamente, pero aún no se ha configurado. +welcome_to = Bienvenido a { $app } +welcome_intro = Esta página se utiliza para probar el correcto funcionamiento de { $app } después de la instalación. +welcome_pagetop = Esta solución web funciona con { $pagetop }. -title_normal_user = ¿Sólo de visita? -text1_normal_user = Si usted es un usuario normal de este sitio web y no sabe de qué trata esta página, probablemente significa que el sitio está experimentando problemas o está pasando por un mantenimiento de rutina. -text2_normal_user = Si el problema persiste, póngase en contacto con el administrador del sistema. +visiting_title = ¿Sólo de visita? +visiting_subtitle = ¿Eres usuario de este sitio web? +visiting_text1 = Si no sabes de qué trata esta página, probablemente significa que el sitio está experimentando problemas o está pasando por un mantenimiento de rutina. +visiting_text2 = Si el problema persiste, póngase en contacto con el administrador del sistema. -title_about_pagetop = Sobre PageTop -text1_about_pagetop = PageTop define una interfaz para los paquetes Rust más estables y populares para crear soluciones web modulares, extensibles y configurables. -text2_about_pagetop = Para obtener información sobre PageTop, visite el "sitio web de PageTop". +pagetop_title = Sobre PageTop +pagetop_text1 = Si puedes leer esta página, significa que el servidor PageTop funciona correctamente, pero aún no se ha configurado. +pagetop_text2 = PageTop define una interfaz para los paquetes Rust más estables y populares para crear soluciones web modulares, extensibles y configurables. +pagetop_text3 = Para obtener información sobre PageTop, visita el "sitio web de PageTop". -title_promo_pagetop = Promociona PageTop -text1_promo_pagetop = Puede usar la siguiente imagen en aplicaciones desarrolladas sobre { $pagetop }. ¡Gracias por usar PageTop! +pagetop_promo_title = Promociona PageTop +pagetop_promo_text1 = Puedes usar la siguiente imagen en aplicaciones desarrolladas sobre { $pagetop }. ¡Gracias por usar PageTop! -title_report_problems = Informando Problemas -text1_report_problems = Utilice la herramienta GitLab para informar errores en PageTop. Sin embargo, verifique los "informes de errores existentes" antes de informar de un nuevo error. -text2_report_problems = Informe los errores específicos de los módulos (como admin y otros) a los paquetes respectivos, no a PageTop en sí. +report_problems_title = Informando Problemas +report_problems_text1 = Utilice la herramienta GitLab para informar errores en PageTop. Sin embargo, verifique los "informes de errores existentes" antes de informar de un nuevo error. +report_problems_text2 = Informe los errores específicos de los módulos (como admin y otros) a los paquetes respectivos, no a PageTop en sí. diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index bb6e3b94..f3d3a903 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -18,61 +18,210 @@ impl ModuleTrait for DemopageModule { } fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { - cfg.route("/", app::web::get().to(home)); + cfg.route("/", app::web::get().to(demo)); } } -async fn home() -> app::Result { - Page::prepare() +async fn demo() -> app::Result { + Page::new() .using_theme("Bootsier") - .with_title( - l("page_title").as_str() - ) - - - - .add_to("content", Container::prepare() - .with_id("welcome") - .add(Chunck::markup(html! { - h1 { (l("page_title")) } - p { (e("text_welcome", &args![ - "app" => format!("{}", &SETTINGS.app.name), - "pagetop" => "PageTop" - ])) } - })) - ) - .add_to("content", Container::prepare() - .add(Container::row() - .add(Container::column() - .with_id("visitors") - .add(Chunck::markup(html! { - h2 { (l("title_normal_user")) } - p { (l("text1_normal_user")) } - p { (l("text2_normal_user")) } - }))) - .add(Container::column() - .with_id("pagetop") - .add(Chunck::markup(html! { - h2 { (l("title_about_pagetop")) } - p { (l("text1_about_pagetop")) } - p { (l("text2_about_pagetop")) } - - h2 { (l("title_promo_pagetop")) } - p { (e("text1_promo_pagetop", &args![ - "pagetop" => - "PageTop" - ])) } - })) - ) - ) - ) - .add_to("content", Container::prepare() - .with_id("reporting") - .add(Chunck::markup(html! { - h2 { (l("title_report_problems")) } - p { (l("text1_report_problems")) } - p { (l("text2_report_problems")) } - })) - ) + .with_title(l("page_title").as_str()) + .add_to("content", hello_world()) + .add_to("content", hello_world2()) + .add_to("content", just_visiting()) + .add_to("content", about_pagetop()) + .add_to("content", promo_pagetop()) + .add_to("content", reporting_problems()) .render() } + +fn hello_world2() -> Container { + Container::header() + .add(grid::Row::new() + .add_column(grid::Column::new() + .add(Chunck::with(html! { + div class="section-title" { + (t("welcome_to", &args![ + "app" => SETTINGS.app.name.as_str() + ])) + } + h1 class="h1-large" { + (l("page_title")) + } + p class="p-large" { + (e("welcome_intro", &args![ + "app" => format!( + "{}", + &SETTINGS.app.name + ) + ])) + } + p { + (e("welcome_pagetop", &args![ + "pagetop" => "PageTop" + ])) + } + a class="btn-solid-lg" href="#services" { + "Offered services" + } + a class="quote" href="#contact" { + i class="fas fa-paper-plane" {} + "Get quote" + } + })) + ) + .add_column(grid::Column::new() + .add(Image::image("/bootsier/images/demo-header.svg")) + ) + ) +} + +fn hello_world() -> Chunck { + Chunck::with(html! { + header id="header" class="header" { + div class="container" { + div class="row" { + div class="col-lg-6 col-xl-5" { + div class="text-container" { + div class="section-title" { + (t("welcome_to", &args![ + "app" => SETTINGS.app.name.as_str() + ])) + } + h1 class="h1-large" { + (l("page_title")) + } + p class="p-large" { + (e("welcome_intro", &args![ + "app" => format!( + "{}", + &SETTINGS.app.name + ) + ])) + } + p { + (e("welcome_pagetop", &args![ + "pagetop" => "PageTop" + ])) + } + a class="btn-solid-lg" href="#services" { + "Offered services" + } + a class="quote" href="#contact" { + i class="fas fa-paper-plane" {} + "Get quote" + } + } + } + div class="col-lg-6 col-xl-7" { + div class="image-container" { + img class="img-fluid" src="/bootsier/images/demo-header.svg" alt="alternative" {} + } + } + } + } + } + }) +} + +fn just_visiting() -> Chunck { + Chunck::with(html! { + div id="details" class="basic-1" { + div class="container" { + div class="row" { + div class="col-lg-6 col-xl-7" { + div class="image-container" { + img class="img-fluid" src="/bootsier/images/demo-visiting.svg" alt="alternative" {} + } + } + div class="col-lg-6 col-xl-5" { + div class="text-container" { + h2 { + span { + (l("visiting_title")) + } + br {} + (l("visiting_subtitle")) + } + p { (l("visiting_text1")) } + p { (l("visiting_text2")) } + a class="btn-solid-reg" data-bs-toggle="modal" data-bs-target="#staticBackdrop" { "Modal" } + } + } + } + } + } + }) +} + +fn about_pagetop() -> Chunck { + Chunck::with(html! { + div id="pagetop" class="basic-2" { + div class="container" { + div class="row" { + div class="col-lg-6 col-xl-5" { + div class="text-container" { + h2 { (l("pagetop_title")) } + p { (l("pagetop_text1")) } + p { (l("pagetop_text2")) } + p { (l("pagetop_text3")) } + } + } + div class="col-lg-6 col-xl-7" { + div class="image-container" { + img class="img-fluid" src="/bootsier/images/demo-pagetop.svg" alt="alternative" {} + } + } + } + } + } + }) +} + +fn promo_pagetop() -> Chunck { + Chunck::with(html! { + div id="promo" class="basic-3" { + div class="container" { + div class="row" { + div class="col-lg-6 col-xl-5" { + div class="text-container" { + h2 { (l("pagetop_promo_title")) } + p { (e("pagetop_promo_text1", &args![ + "pagetop" => + "PageTop" + ])) } + } + } + div class="col-lg-6 col-xl-7" { + div class="image-container" { + img class="img-fluid" src="/bootsier/images/demo-pagetop.svg" alt="alternative" {} + } + } + } + } + } + }) +} + +fn reporting_problems() -> Chunck { + Chunck::with(html! { + div id="reporting" class="basic-4" { + div class="container" { + div class="row" { + div class="col-lg-6 col-xl-5" { + div class="text-container" { + h2 { (l("report_problems_title")) } + p { (l("report_problems_text1")) } + p { (l("report_problems_text2")) } + } + } + div class="col-lg-6 col-xl-7" { + div class="image-container" { + img class="img-fluid" src="/bootsier/images/demo-pagetop.svg" alt="alternative" {} + } + } + } + } + } + }) +} diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index ada65b0e..90111723 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -52,9 +52,9 @@ impl ThemeTrait for BootsierTheme { s = app::http::StatusCode::INTERNAL_SERVER_ERROR; } } - Page::prepare() + Page::new() .with_title(format!("Error {}", s.as_str()).as_str()) - .add_to("content", Chunck::markup(html! { + .add_to("content", Chunck::with(html! { div class="jumbotron" { div class="media" { img diff --git a/pagetop/src/html.rs b/pagetop/src/html.rs deleted file mode 100644 index ba885bb3..00000000 --- a/pagetop/src/html.rs +++ /dev/null @@ -1 +0,0 @@ -pub use maud::{DOCTYPE, Markup, PreEscaped, html}; diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs new file mode 100644 index 00000000..16c5ac73 --- /dev/null +++ b/pagetop/src/html/classes.rs @@ -0,0 +1,63 @@ +pub struct Classes { + classes: Vec, + option : Option, + updated: bool, +} + +impl Classes { + pub fn none() -> Self { + Classes { + classes: Vec::new(), + option : None, + updated: true, + } + } + + pub fn some_class(class: &str) -> Self { + let mut c = Classes::none(); + c.add_class(class); + c + } + + pub fn some_classes(classes: Vec) -> Self { + let mut c = Classes::none(); + c.add_classes(classes); + c + } + + pub fn add_class(&mut self, class: &str) { + let class = class.trim().replace(" ", "_"); + if !class.is_empty() && !self.classes.iter().any(|c| *c == class) { + self.classes.push(class.to_owned()); + self.updated = false; + } + } + + pub fn add_classes(&mut self, classes: Vec) { + for class in classes.iter() { + self.add_class(class); + } + } + + pub fn classes(&mut self) -> &str { + match self.option() { + Some(classes) => classes.as_str(), + None => "", + } + } + + pub fn has_classes(&self) -> bool { + self.classes.len() > 0 + } + + pub fn option(&mut self) -> &Option { + if !self.updated { + self.option = match self.classes.len() { + 0 => None, + _ => Some(self.classes.join(" ")), + }; + self.updated = true; + } + &self.option + } +} diff --git a/pagetop/src/html/mod.rs b/pagetop/src/html/mod.rs new file mode 100644 index 00000000..60a9bd82 --- /dev/null +++ b/pagetop/src/html/mod.rs @@ -0,0 +1,8 @@ +pub use maud::{DOCTYPE, Markup, PreEscaped, html}; + +mod optional_id; +pub use optional_id::OptionId; +mod optional_attr; +pub use optional_attr::OptionAttr; +mod classes; +pub use classes::Classes; diff --git a/pagetop/src/html/optional_attr.rs b/pagetop/src/html/optional_attr.rs new file mode 100644 index 00000000..f6b48189 --- /dev/null +++ b/pagetop/src/html/optional_attr.rs @@ -0,0 +1,41 @@ +pub struct OptionAttr(Option); + +impl OptionAttr { + pub fn none() -> Self { + OptionAttr(None) + } + + pub fn some(value: &str) -> Self { + let value = value.trim(); + match value.is_empty() { + true => OptionAttr(None), + false => OptionAttr(Some(value.to_owned())), + } + } + + pub fn with_value(&mut self, value: &str) { + let value = value.trim(); + self.0 = match value.is_empty() { + true => None, + false => Some(value.to_owned()), + }; + } + + pub fn value(&self) -> &str { + match &self.0 { + Some(value) => value.as_str(), + None => "", + } + } + + pub fn has_value(&self) -> bool { + match &self.0 { + Some(_) => true, + None => false, + } + } + + pub fn option(&self) -> &Option { + &self.0 + } +} diff --git a/pagetop/src/html/optional_id.rs b/pagetop/src/html/optional_id.rs new file mode 100644 index 00000000..678ff5c8 --- /dev/null +++ b/pagetop/src/html/optional_id.rs @@ -0,0 +1,33 @@ +pub struct OptionId(Option); + +impl OptionId { + pub fn none() -> Self { + OptionId(None) + } + + pub fn with_value(&mut self, id: &str) { + let id = id.trim(); + self.0 = match id.is_empty() { + true => None, + false => Some(id.replace(" ", "_")), + }; + } + + pub fn value(&self) -> &str { + match &self.0 { + Some(id) => id.as_str(), + None => "", + } + } + + pub fn has_value(&self) -> bool { + match &self.0 { + Some(_) => true, + None => false, + } + } + + pub fn option(&self) -> &Option { + &self.0 + } +} diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 26151cab..630b8a9b 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -7,7 +7,7 @@ use std::any::type_name; pub trait PageComponent: Downcast + Send + Sync { - fn prepare() -> Self where Self: Sized; + fn new() -> Self where Self: Sized; fn name(&self) -> &'static str { let name = type_name::(); diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index eff38daa..1ccb9603 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,9 +1,8 @@ -use crate::{Lazy, app, trace, util}; +use crate::{Lazy, app, trace}; use crate::config::SETTINGS; -use crate::html::{DOCTYPE, Markup, html}; +use crate::html::{Classes, DOCTYPE, Markup, OptionAttr, html}; use crate::response::page::{PageAssets, PageComponent, PageContainer}; -use std::borrow::Cow; use std::sync::RwLock; use std::collections::HashMap; @@ -41,31 +40,31 @@ static DEFAULT_DIRECTION: Lazy> = Lazy::new(|| { pub enum TextDirection { Auto, LeftToRight, RightToLeft } pub struct Page<'a> { - language : Option, - direction : Option, - title : Option, - description : Option, + language : OptionAttr, + direction : OptionAttr, + title : OptionAttr, + description : OptionAttr, assets : PageAssets, - body_classes: Cow<'a, str>, + body_classes: Classes, regions : HashMap<&'a str, PageContainer>, template : String, } impl<'a> Page<'a> { - pub fn prepare() -> Self { + pub fn new() -> Self { Page { language : match &*DEFAULT_LANGUAGE { - Some(language) => Some(language.to_owned()), - _ => None, + Some(language) => OptionAttr::some(language), + _ => OptionAttr::none(), }, direction : match &*DEFAULT_DIRECTION { - Some(direction) => Some(direction.to_owned()), - _ => None, + Some(direction) => OptionAttr::some(direction), + _ => OptionAttr::none(), }, - title : None, - description : None, - body_classes: "body".into(), + title : OptionAttr::none(), + description : OptionAttr::none(), + body_classes: Classes::some_class("body"), assets : PageAssets::new(), regions : COMPONENTS.read().unwrap().clone(), template : "default".to_owned(), @@ -75,38 +74,36 @@ impl<'a> Page<'a> { // Page BUILDER. pub fn with_language(&mut self, language: &str) -> &mut Self { - self.language = util::valid_str(language); + self.language.with_value(language); self } pub fn with_direction(&mut self, dir: TextDirection) -> &mut Self { - self.direction = match dir { - TextDirection::Auto => Some("auto".to_owned()), - TextDirection::LeftToRight => Some("ltr".to_owned()), - TextDirection::RightToLeft => Some("rtl".to_owned()), - }; + self.direction.with_value(match dir { + TextDirection::Auto => "auto", + TextDirection::LeftToRight => "ltr", + TextDirection::RightToLeft => "rtl", + }); self } pub fn with_title(&mut self, title: &str) -> &mut Self { - self.title = util::valid_str(title); + self.title.with_value(title); self } pub fn with_description(&mut self, description: &str) -> &mut Self { - self.description = util::valid_str(description); + self.description.with_value(description); self } - pub fn with_body_classes(&mut self, body_classes: &'a str) -> &mut Self { - self.body_classes = body_classes.into(); + pub fn add_body_class(&mut self, class: &str) -> &mut Self { + self.body_classes.add_class(class); self } - pub fn add_body_classes(&mut self, body_classes: &'a str) -> &mut Self { - self.body_classes = String::from( - format!("{} {}", self.body_classes, body_classes).trim() - ).into(); + pub fn add_body_classes(&mut self, classes: Vec) -> &mut Self { + self.body_classes.add_classes(classes); self } @@ -131,26 +128,23 @@ impl<'a> Page<'a> { // Page GETTERS. pub fn language(&self) -> &str { - util::assigned_str(&self.language) + self.language.value() } pub fn direction(&self) -> &str { - util::assigned_str(&self.direction) + self.direction.value() } pub fn title(&self) -> &str { - util::assigned_str(&self.title) + self.title.value() } pub fn description(&self) -> &str { - util::assigned_str(&self.description) + self.description.value() } - pub fn body_classes(&self) -> &str { - if self.body_classes.is_empty() { - return "body"; - } - &self.body_classes + pub fn body_classes(&mut self) -> &str { + self.body_classes.classes() } pub fn assets(&mut self) -> &mut PageAssets { @@ -176,7 +170,7 @@ impl<'a> Page<'a> { // Finalmente, renderizar la página. return Ok(html! { (DOCTYPE) - html lang=[&self.language] dir=[&self.direction] { + html lang=[&self.language.option()] dir=[&self.direction.option()] { (head) (body) } @@ -204,7 +198,7 @@ pub fn render_component( ) -> Markup { match component.is_renderable() { true => match assets.theme().render_component(component, assets) { - Some(markup) => markup, + Some(html) => html, None => component.default_render(assets) }, false => html! {} diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 733736e2..15f6566e 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -99,9 +99,9 @@ pub trait ThemeTrait: Send + Sync { } fn render_error_page(&self, s: app::http::StatusCode) -> app::Result { - Page::prepare() + Page::new() .with_title(format!("Error {}", s.as_str()).as_str()) - .add_to("content", Chunck::markup(html! { + .add_to("content", Chunck::with(html! { div { h1 { (s) } } diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index 4ba4f76e..c2fd58d3 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -35,26 +35,3 @@ macro_rules! theme_static_files { } }}; } - -pub fn valid_id(id: &str) -> Option { - let id = id.trim(); - match id.is_empty() { - true => None, - false => Some(id.replace(" ", "_").to_lowercase()), - } -} - -pub fn valid_str(s: &str) -> Option { - let s = s.trim(); - match s.is_empty() { - true => None, - false => Some(s.to_owned()), - } -} - -pub fn assigned_str(optional: &Option) -> &str { - match optional { - Some(o) => o.as_str(), - None => "", - } -} diff --git a/pagetop/static/bootsier/images/demo-header.svg b/pagetop/static/bootsier/images/demo-header.svg new file mode 100644 index 00000000..060757ee --- /dev/null +++ b/pagetop/static/bootsier/images/demo-header.svg @@ -0,0 +1 @@ +header-illustration \ No newline at end of file diff --git a/pagetop/static/bootsier/images/demo-pagetop.svg b/pagetop/static/bootsier/images/demo-pagetop.svg new file mode 100644 index 00000000..08fbbb09 --- /dev/null +++ b/pagetop/static/bootsier/images/demo-pagetop.svg @@ -0,0 +1 @@ +details-2 \ No newline at end of file diff --git a/pagetop/static/bootsier/images/demo-visiting.svg b/pagetop/static/bootsier/images/demo-visiting.svg new file mode 100644 index 00000000..d06680b3 --- /dev/null +++ b/pagetop/static/bootsier/images/demo-visiting.svg @@ -0,0 +1 @@ +details-1 \ No newline at end of file From b02a92dbb055906df4402329c59e8f2465b836d1 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 27 Mar 2022 13:07:16 +0200 Subject: [PATCH 10/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- pagetop/src/base/component/block.rs | 8 +-- pagetop/src/base/component/container.rs | 4 +- pagetop/src/base/component/form/button.rs | 20 +++---- pagetop/src/base/component/form/date.rs | 48 ++++++++-------- pagetop/src/base/component/form/form.rs | 12 ++-- pagetop/src/base/component/form/hidden.rs | 12 ++-- pagetop/src/base/component/form/input.rs | 56 +++++++++---------- pagetop/src/base/component/grid/column.rs | 4 +- pagetop/src/base/component/grid/row.rs | 4 +- pagetop/src/base/component/menu.rs | 4 +- pagetop/src/base/module/demopage/mod.rs | 6 +- pagetop/src/html/mod.rs | 8 +-- .../src/html/{optional_attr.rs => optattr.rs} | 10 ++-- .../src/html/{optional_id.rs => optiden.rs} | 6 +- pagetop/src/response/page/page.rs | 22 ++++---- 16 files changed, 113 insertions(+), 113 deletions(-) rename pagetop/src/html/{optional_attr.rs => optattr.rs} (80%) rename pagetop/src/html/{optional_id.rs => optiden.rs} (88%) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index a260d17f..514ab6e9 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.4" +version = "0.0.5" edition = "2021" authors = [ diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index b857712f..5e5a7159 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -3,8 +3,8 @@ use crate::prelude::*; pub struct Block { renderable: fn() -> bool, weight : i8, - id : OptionId, - title : OptionAttr, + id : OptIden, + title : OptAttr, html : Vec, template : String, } @@ -15,8 +15,8 @@ impl PageComponent for Block { Block { renderable: always, weight : 0, - id : OptionId::none(), - title : OptionAttr::none(), + id : OptIden::none(), + title : OptAttr::none(), html : Vec::new(), template : "default".to_owned(), } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 18d6337a..e76b48b4 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -5,7 +5,7 @@ enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable: fn() -> bool, weight : i8, - id : OptionId, + id : OptIden, container : ContainerType, components: PageContainer, template : String, @@ -17,7 +17,7 @@ impl PageComponent for Container { Container { renderable: always, weight : 0, - id : OptionId::none(), + id : OptIden::none(), container : ContainerType::Wrapper, components: PageContainer::new(), template : "default".to_owned(), diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index a1975ea4..fa9794f2 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -6,10 +6,10 @@ pub struct Button { renderable : fn() -> bool, weight : i8, button_type: ButtonType, - name : OptionAttr, - value : OptionAttr, - autofocus : OptionAttr, - disabled : OptionAttr, + name : OptAttr, + value : OptAttr, + autofocus : OptAttr, + disabled : OptAttr, template : String, } @@ -20,10 +20,10 @@ impl PageComponent for Button { renderable : always, weight : 0, button_type: ButtonType::Button, - name : OptionAttr::none(), - value : OptionAttr::none(), - autofocus : OptionAttr::none(), - disabled : OptionAttr::none(), + name : OptAttr::none(), + value : OptAttr::none(), + autofocus : OptAttr::none(), + disabled : OptAttr::none(), template : "default".to_owned(), } } @@ -42,14 +42,14 @@ impl PageComponent for Button { ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), ButtonType::Submit => ("submit", "btn btn-primary form-submit") }; - let id_item = match &self.name.option() { + let id = match &self.name.option() { Some(name) => Some(format!("edit-{}", name)), _ => None }; html! { button type=(button_type) - id=[&id_item] + id=[&id] class=(button_class) name=[&self.name.option()] value=[&self.value.option()] diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 7f04691b..5e42bc6b 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -3,16 +3,16 @@ use crate::prelude::*; pub struct Date { renderable : fn() -> bool, weight : i8, - name : OptionAttr, - value : OptionAttr, - label : OptionAttr, - placeholder : OptionAttr, - autofocus : OptionAttr, - autocomplete: OptionAttr, - disabled : OptionAttr, - readonly : OptionAttr, - required : OptionAttr, - help_text : OptionAttr, + name : OptAttr, + value : OptAttr, + label : OptAttr, + placeholder : OptAttr, + autofocus : OptAttr, + autocomplete: OptAttr, + disabled : OptAttr, + readonly : OptAttr, + required : OptAttr, + help_text : OptAttr, template : String, } @@ -22,16 +22,16 @@ impl PageComponent for Date { Date { renderable : always, weight : 0, - name : OptionAttr::none(), - value : OptionAttr::none(), - label : OptionAttr::none(), - placeholder : OptionAttr::none(), - autofocus : OptionAttr::none(), - autocomplete: OptionAttr::none(), - disabled : OptionAttr::none(), - readonly : OptionAttr::none(), - required : OptionAttr::none(), - help_text : OptionAttr::none(), + name : OptAttr::none(), + value : OptAttr::none(), + label : OptAttr::none(), + placeholder : OptAttr::none(), + autofocus : OptAttr::none(), + autocomplete: OptAttr::none(), + disabled : OptAttr::none(), + readonly : OptAttr::none(), + required : OptAttr::none(), + help_text : OptAttr::none(), template : "default".to_owned(), } } @@ -45,7 +45,7 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (class_item, id_item) = match self.name.option() { + let (class, id) = match self.name.option() { Some(name) => ( format!("form-item form-item-{} form-type-date", name), Some(format!("edit-{}", name)) @@ -56,9 +56,9 @@ impl PageComponent for Date { ) }; html! { - div class=(class_item) { + div class=(class) { @if self.label.has_value() { - label class="form-label" for=[&id_item] { + label class="form-label" for=[&id] { (self.label.value()) " " @if self.required.has_value() { span @@ -72,7 +72,7 @@ impl PageComponent for Date { } input type="date" - id=[&id_item] + id=[&id] class="form-control" name=[&self.name.option()] value=[&self.value.option()] diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index e93926a7..385dd369 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -5,10 +5,10 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : i8, - id : OptionId, - action : OptionAttr, + id : OptIden, + action : OptAttr, method : FormMethod, - charset : OptionAttr, + charset : OptAttr, elements : PageContainer, template : String, } @@ -19,10 +19,10 @@ impl PageComponent for Form { Form { renderable: always, weight : 0, - id : OptionId::none(), - action : OptionAttr::none(), + id : OptIden::none(), + action : OptAttr::none(), method : FormMethod::Post, - charset : OptionAttr::some("UTF-8"), + charset : OptAttr::some("UTF-8"), elements : PageContainer::new(), template : "default".to_owned(), } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index b27caf37..b7eca015 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -2,8 +2,8 @@ use crate::prelude::*; pub struct Hidden { weight : i8, - name : OptionId, - value : OptionAttr, + name : OptIden, + value : OptAttr, } impl PageComponent for Hidden { @@ -11,8 +11,8 @@ impl PageComponent for Hidden { fn new() -> Self { Hidden { weight : 0, - name : OptionId::none(), - value : OptionAttr::none(), + name : OptIden::none(), + value : OptAttr::none(), } } @@ -21,14 +21,14 @@ impl PageComponent for Hidden { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let id_item = match self.name.option() { + let id = match self.name.option() { Some(name) => Some(format!("value-{}", name)), _ => None }; html! { input type="hidden" - id=[&id_item] + id=[&id] name=[&self.name.option()] value=[&self.value.option()]; } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index c483c9a9..7622fd08 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -6,19 +6,19 @@ pub struct Input { renderable : fn() -> bool, weight : i8, input_type : InputType, - name : OptionId, - value : OptionAttr, - label : OptionAttr, + name : OptIden, + value : OptAttr, + label : OptAttr, size : Option, minlength : Option, maxlength : Option, - placeholder : OptionAttr, - autofocus : OptionAttr, - autocomplete: OptionAttr, - disabled : OptionAttr, - readonly : OptionAttr, - required : OptionAttr, - help_text : OptionAttr, + placeholder : OptAttr, + autofocus : OptAttr, + autocomplete: OptAttr, + disabled : OptAttr, + readonly : OptAttr, + required : OptAttr, + help_text : OptAttr, template : String, } @@ -29,19 +29,19 @@ impl PageComponent for Input { renderable : always, weight : 0, input_type : InputType::Textfield, - name : OptionId::none(), - value : OptionAttr::none(), - label : OptionAttr::none(), + name : OptIden::none(), + value : OptAttr::none(), + label : OptAttr::none(), size : Some(60), minlength : None, maxlength : Some(128), - placeholder : OptionAttr::none(), - autofocus : OptionAttr::none(), - autocomplete: OptionAttr::none(), - disabled : OptionAttr::none(), - readonly : OptionAttr::none(), - required : OptionAttr::none(), - help_text : OptionAttr::none(), + placeholder : OptAttr::none(), + autofocus : OptAttr::none(), + autocomplete: OptAttr::none(), + disabled : OptAttr::none(), + readonly : OptAttr::none(), + required : OptAttr::none(), + help_text : OptAttr::none(), template : "default".to_owned(), } } @@ -55,7 +55,7 @@ impl PageComponent for Input { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (input_type, class_type) = match &self.input_type { + let (type_input, type_class) = match &self.input_type { InputType::Email => ("email", "form-type-email"), InputType::Password => ("password", "form-type-password"), InputType::Search => ("search", "form-type-search"), @@ -63,20 +63,20 @@ impl PageComponent for Input { InputType::Textfield => ("text", "form-type-textfield"), InputType::Url => ("url", "form-type-url") }; - let (class_item, id_item) = match &self.name.option() { + let (class, id) = match &self.name.option() { Some(name) => ( - format!("form-item form-item-{} {}", name, class_type), + format!("form-item form-item-{} {}", name, type_class), Some(format!("edit-{}", name)) ), None => ( - format!("form-item {}", class_type), + format!("form-item {}", type_class), None ) }; html! { - div class=(class_item) { + div class=(class) { @if self.label.has_value() { - label class="form-label" for=[&id_item] { + label class="form-label" for=[&id] { (self.label.value()) " " @if self.required.has_value() { span @@ -89,8 +89,8 @@ impl PageComponent for Input { } } input - type=(input_type) - id=[&id_item] + type=(type_input) + id=[&id] class="form-control" name=[&self.name.option()] value=[&self.value.option()] diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 96463490..8bcfb54f 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub struct Column { renderable: fn() -> bool, weight : i8, - id : OptionId, + id : OptIden, components: PageContainer, template : String, } @@ -14,7 +14,7 @@ impl PageComponent for Column { Column { renderable: always, weight : 0, - id : OptionId::none(), + id : OptIden::none(), components: PageContainer::new(), template : "default".to_owned(), } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 6aed7d0f..7c94fea6 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub struct Row { renderable: fn() -> bool, weight : i8, - id : OptionId, + id : OptIden, columns : PageContainer, template : String, } @@ -14,7 +14,7 @@ impl PageComponent for Row { Row { renderable: always, weight : 0, - id : OptionId::none(), + id : OptIden::none(), columns : PageContainer::new(), template : "default".to_owned(), } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 10ac8ca5..0f529874 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -148,7 +148,7 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, weight : i8, - id : OptionId, + id : OptIden, items : PageContainer, template : String, } @@ -159,7 +159,7 @@ impl PageComponent for Menu { Menu { renderable: always, weight : 0, - id : OptionId::none(), + id : OptIden::none(), items : PageContainer::new(), template : "default".to_owned(), } diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index f3d3a903..7fa78181 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -27,7 +27,7 @@ async fn demo() -> app::Result { .using_theme("Bootsier") .with_title(l("page_title").as_str()) .add_to("content", hello_world()) - .add_to("content", hello_world2()) + .add_to("content", hello_world_original()) .add_to("content", just_visiting()) .add_to("content", about_pagetop()) .add_to("content", promo_pagetop()) @@ -35,7 +35,7 @@ async fn demo() -> app::Result { .render() } -fn hello_world2() -> Container { +fn hello_world() -> Container { Container::header() .add(grid::Row::new() .add_column(grid::Column::new() @@ -76,7 +76,7 @@ fn hello_world2() -> Container { ) } -fn hello_world() -> Chunck { +fn hello_world_original() -> Chunck { Chunck::with(html! { header id="header" class="header" { div class="container" { diff --git a/pagetop/src/html/mod.rs b/pagetop/src/html/mod.rs index 60a9bd82..52f735fe 100644 --- a/pagetop/src/html/mod.rs +++ b/pagetop/src/html/mod.rs @@ -1,8 +1,8 @@ pub use maud::{DOCTYPE, Markup, PreEscaped, html}; -mod optional_id; -pub use optional_id::OptionId; -mod optional_attr; -pub use optional_attr::OptionAttr; +mod optiden; +pub use optiden::OptIden; +mod optattr; +pub use optattr::OptAttr; mod classes; pub use classes::Classes; diff --git a/pagetop/src/html/optional_attr.rs b/pagetop/src/html/optattr.rs similarity index 80% rename from pagetop/src/html/optional_attr.rs rename to pagetop/src/html/optattr.rs index f6b48189..af82751c 100644 --- a/pagetop/src/html/optional_attr.rs +++ b/pagetop/src/html/optattr.rs @@ -1,15 +1,15 @@ -pub struct OptionAttr(Option); +pub struct OptAttr(Option); -impl OptionAttr { +impl OptAttr { pub fn none() -> Self { - OptionAttr(None) + OptAttr(None) } pub fn some(value: &str) -> Self { let value = value.trim(); match value.is_empty() { - true => OptionAttr(None), - false => OptionAttr(Some(value.to_owned())), + true => OptAttr(None), + false => OptAttr(Some(value.to_owned())), } } diff --git a/pagetop/src/html/optional_id.rs b/pagetop/src/html/optiden.rs similarity index 88% rename from pagetop/src/html/optional_id.rs rename to pagetop/src/html/optiden.rs index 678ff5c8..ca10155e 100644 --- a/pagetop/src/html/optional_id.rs +++ b/pagetop/src/html/optiden.rs @@ -1,8 +1,8 @@ -pub struct OptionId(Option); +pub struct OptIden(Option); -impl OptionId { +impl OptIden { pub fn none() -> Self { - OptionId(None) + OptIden(None) } pub fn with_value(&mut self, id: &str) { diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 1ccb9603..5bd4696a 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,6 +1,6 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; -use crate::html::{Classes, DOCTYPE, Markup, OptionAttr, html}; +use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html}; use crate::response::page::{PageAssets, PageComponent, PageContainer}; use std::sync::RwLock; @@ -40,10 +40,10 @@ static DEFAULT_DIRECTION: Lazy> = Lazy::new(|| { pub enum TextDirection { Auto, LeftToRight, RightToLeft } pub struct Page<'a> { - language : OptionAttr, - direction : OptionAttr, - title : OptionAttr, - description : OptionAttr, + language : OptAttr, + direction : OptAttr, + title : OptAttr, + description : OptAttr, assets : PageAssets, body_classes: Classes, regions : HashMap<&'a str, PageContainer>, @@ -55,15 +55,15 @@ impl<'a> Page<'a> { pub fn new() -> Self { Page { language : match &*DEFAULT_LANGUAGE { - Some(language) => OptionAttr::some(language), - _ => OptionAttr::none(), + Some(language) => OptAttr::some(language), + _ => OptAttr::none(), }, direction : match &*DEFAULT_DIRECTION { - Some(direction) => OptionAttr::some(direction), - _ => OptionAttr::none(), + Some(direction) => OptAttr::some(direction), + _ => OptAttr::none(), }, - title : OptionAttr::none(), - description : OptionAttr::none(), + title : OptAttr::none(), + description : OptAttr::none(), body_classes: Classes::some_class("body"), assets : PageAssets::new(), regions : COMPONENTS.read().unwrap().clone(), From 2476b2b9c8ff636d6028430fb6bbba3d3054931b Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 28 Mar 2022 01:08:22 +0200 Subject: [PATCH 11/80] =?UTF-8?q?Corrige=20el=20r=C3=B3tulo=20de=20inicio?= =?UTF-8?q?=20en=20terminales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajusta el número de caracteres que se pueden mostrar en el rótulo de inicio según el número de columnas del terminal. Si es menor de 80 columnas mostrará directamente texto. --- pagetop/Cargo.toml | 2 ++ pagetop/src/app/banner/mod.rs | 20 ++++++++++++++++++-- pagetop/src/lib.rs | 8 ++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 514ab6e9..a4db3d98 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -27,6 +27,8 @@ downcast-rs = "1.2.0" figlet-rs = "0.1.3" futures = "0.3.21" once_cell = "1.10.0" +substring = "1.4.5" +term_size = "0.3.2" url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } diff --git a/pagetop/src/app/banner/mod.rs b/pagetop/src/app/banner/mod.rs index f6d63841..1cce7146 100644 --- a/pagetop/src/app/banner/mod.rs +++ b/pagetop/src/app/banner/mod.rs @@ -2,6 +2,7 @@ use crate::Lazy; use crate::config::SETTINGS; use figlet_rs::FIGfont; +use substring::Substring; static FIGFONT: Lazy = Lazy::new(|| { let slant = include_str!("slant.flf"); @@ -31,8 +32,23 @@ static FIGFONT: Lazy = Lazy::new(|| { pub fn print_on_startup() { if SETTINGS.app.startup_banner.to_lowercase() != "off" { - println!("\n{} {}\n\n Powered by PageTop {}\n", - FIGFONT.convert(&SETTINGS.app.name).unwrap(), + if let Some((term_width, _)) = term_size::dimensions() { + if term_width >= 80 { + let maxlen = (term_width / 10) - 2; + let mut app = SETTINGS.app.name.substring(0, maxlen).to_owned(); + if SETTINGS.app.name.len() > maxlen { + app = format!("{}...", app); + } + println!("\n{} {}\n\n Powered by PageTop {}\n", + FIGFONT.convert(&app).unwrap(), + &SETTINGS.app.description, + env!("CARGO_PKG_VERSION") + ); + return; + } + } + println!("\n{}\n{}\n\nPowered by PageTop {}\n", + &SETTINGS.app.name, &SETTINGS.app.description, env!("CARGO_PKG_VERSION") ); diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 73e17c8d..72ab7328 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,8 +1,8 @@ -// Global. +// Local. -pub use doc_comment::doc_comment; -pub use once_cell::sync::Lazy; -pub use futures::executor::block_on as run_now; +pub(crate) use doc_comment::doc_comment; +pub(crate) use once_cell::sync::Lazy; +pub(crate) use futures::executor::block_on as run_now; // ----------------------------------------------------------------------------- // APIs públicas. From 5aee113f547e93212a977ffbbda00e618660b697 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 28 Mar 2022 21:19:02 +0200 Subject: [PATCH 12/80] =?UTF-8?q?A=C3=B1ade=20el=20tema=20Bulmix=20basado?= =?UTF-8?q?=20en=20el=20framework=20Bulma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/default.toml | 1 + pagetop/Cargo.toml | 17 +++--- pagetop/build.rs | 8 +++ pagetop/src/app/application.rs | 1 + pagetop/src/base/component/grid/column.rs | 9 ++- pagetop/src/base/component/grid/row.rs | 9 ++- pagetop/src/base/module/demopage/mod.rs | 2 +- pagetop/src/base/theme/bulmix/mod.rs | 34 +++++++++++ pagetop/src/base/theme/mod.rs | 3 +- pagetop/src/html/classes.rs | 61 +++++++------------ pagetop/src/html/optattr.rs | 13 ++-- pagetop/src/html/optiden.rs | 11 ++-- pagetop/src/lib.rs | 1 + pagetop/src/response/page/page.rs | 9 +-- pagetop/static/bulmix/css/bulma-rtl.min.css | 1 + .../static/bulmix/css/bulma-rtl.min.css.map | 1 + pagetop/static/bulmix/css/bulma.min.css | 1 + pagetop/static/bulmix/css/bulma.min.css.map | 1 + 18 files changed, 113 insertions(+), 70 deletions(-) create mode 100644 pagetop/src/base/theme/bulmix/mod.rs create mode 100644 pagetop/static/bulmix/css/bulma-rtl.min.css create mode 100644 pagetop/static/bulmix/css/bulma-rtl.min.css.map create mode 100644 pagetop/static/bulmix/css/bulma.min.css create mode 100644 pagetop/static/bulmix/css/bulma.min.css.map diff --git a/config/default.toml b/config/default.toml index 13012a93..6d6317f3 100644 --- a/config/default.toml +++ b/config/default.toml @@ -6,6 +6,7 @@ description = """\ #theme = "Aliner" #theme = "Minimal" theme = "Bootsier" +#theme = "Bulmix" language = "es-ES" [database] diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index a4db3d98..01eb60ec 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -22,14 +22,15 @@ categories = [ ] [dependencies] -doc-comment = "0.3.3" -downcast-rs = "1.2.0" -figlet-rs = "0.1.3" -futures = "0.3.21" -once_cell = "1.10.0" -substring = "1.4.5" -term_size = "0.3.2" -url = "2.2.2" +concat-string = "1.0.1" +doc-comment = "0.3.3" +downcast-rs = "1.2.0" +figlet-rs = "0.1.3" +futures = "0.3.21" +once_cell = "1.10.0" +substring = "1.4.5" +term_size = "0.3.2" +url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } diff --git a/pagetop/build.rs b/pagetop/build.rs index bd7e60a0..a8c287a8 100644 --- a/pagetop/build.rs +++ b/pagetop/build.rs @@ -27,4 +27,12 @@ fn main() { ) .build() .unwrap(); + + resource_dir("./static/bulmix") + .with_generated_filename( + Path::new(env::var("OUT_DIR").unwrap().as_str()) + .join("bulmix.rs") + ) + .build() + .unwrap(); } diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 070390c8..f0473180 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -31,6 +31,7 @@ impl Application { theme::register_theme(&base::theme::aliner::AlinerTheme); theme::register_theme(&base::theme::minimal::MinimalTheme); theme::register_theme(&base::theme::bootsier::BootsierTheme); + theme::register_theme(&base::theme::bulmix::BulmixTheme); // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 8bcfb54f..19eb577b 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -4,6 +4,7 @@ pub struct Column { renderable: fn() -> bool, weight : i8, id : OptIden, + classes : Classes, components: PageContainer, template : String, } @@ -15,6 +16,7 @@ impl PageComponent for Column { renderable: always, weight : 0, id : OptIden::none(), + classes : Classes::some(vec!["col"]), components: PageContainer::new(), template : "default".to_owned(), } @@ -30,7 +32,7 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class="col" { + div id=[&self.id.option()] class=[&self.classes.option()] { (self.components.render(assets)) } } @@ -56,6 +58,11 @@ impl Column { self } + pub fn add_classes(mut self, classes: Vec<&str>) -> Self { + self.classes.add_classes(classes); + self + } + pub fn add(mut self, component: impl PageComponent) -> Self { self.components.add(component); self diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 7c94fea6..53719e3f 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -4,6 +4,7 @@ pub struct Row { renderable: fn() -> bool, weight : i8, id : OptIden, + classes : Classes, columns : PageContainer, template : String, } @@ -15,6 +16,7 @@ impl PageComponent for Row { renderable: always, weight : 0, id : OptIden::none(), + classes : Classes::some(vec!["row"]), columns : PageContainer::new(), template : "default".to_owned(), } @@ -30,7 +32,7 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class="row" { + div id=[&self.id.option()] class=[&self.classes.option()] { (self.columns.render(assets)) } } @@ -56,6 +58,11 @@ impl Row { self } + pub fn add_classes(mut self, classes: Vec<&str>) -> Self { + self.classes.add_classes(classes); + self + } + pub fn add_column(mut self, column: grid::Column) -> Self { self.columns.add(column); self diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 7fa78181..c9fc9cc0 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -24,7 +24,7 @@ impl ModuleTrait for DemopageModule { async fn demo() -> app::Result { Page::new() - .using_theme("Bootsier") + .using_theme("Bulmix") .with_title(l("page_title").as_str()) .add_to("content", hello_world()) .add_to("content", hello_world_original()) diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs new file mode 100644 index 00000000..b8d57ba7 --- /dev/null +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -0,0 +1,34 @@ +use crate::prelude::*; + +include!(concat!(env!("OUT_DIR"), "/bulmix.rs")); + +pub struct BulmixTheme; + +impl ThemeTrait for BulmixTheme { + fn name(&self) -> &'static str { + "Bulmix" + } + + fn fullname(&self) -> String { + "Bulmix".to_owned() + } + + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { + theme_static_files!(cfg, "/bulmix"); + } + + fn before_render_page(&self, page: &mut Page) { + page.assets() + .with_favicon( + Favicon::new() + .with_icon("/theme/favicon.png") + ) + .add_stylesheet( + StyleSheet::source( + "/bulmix/css/bulma.min.css?ver=0.9.3" + ) + .with_weight(-99) + ) + .add_jquery(); + } +} diff --git a/pagetop/src/base/theme/mod.rs b/pagetop/src/base/theme/mod.rs index baccfbd9..293e4e88 100644 --- a/pagetop/src/base/theme/mod.rs +++ b/pagetop/src/base/theme/mod.rs @@ -1,3 +1,4 @@ pub mod aliner; -pub mod bootsier; pub mod minimal; +pub mod bootsier; +pub mod bulmix; diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index 16c5ac73..c2a35984 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -1,63 +1,48 @@ -pub struct Classes { - classes: Vec, - option : Option, - updated: bool, -} +use crate::concat_string; + +pub struct Classes(Option); impl Classes { pub fn none() -> Self { - Classes { - classes: Vec::new(), - option : None, - updated: true, - } + Classes(None) } - pub fn some_class(class: &str) -> Self { - let mut c = Classes::none(); - c.add_class(class); - c - } - - pub fn some_classes(classes: Vec) -> Self { + pub fn some(classes: Vec<&str>) -> Self { let mut c = Classes::none(); c.add_classes(classes); c } - pub fn add_class(&mut self, class: &str) { - let class = class.trim().replace(" ", "_"); - if !class.is_empty() && !self.classes.iter().any(|c| *c == class) { - self.classes.push(class.to_owned()); - self.updated = false; - } - } - - pub fn add_classes(&mut self, classes: Vec) { + pub fn add_classes(&mut self, classes: Vec<&str>) { for class in classes.iter() { self.add_class(class); } } - pub fn classes(&mut self) -> &str { - match self.option() { + fn add_class(&mut self, class: &str) { + let class = class.trim().replace(" ", "_"); + if !class.is_empty() { + match &self.0 { + None => self.0 = Some(class), + Some(classes) => if !classes.split(" ").any(|c| *c == class) { + self.0 = Some(concat_string!(classes, " ", class)) + } + } + } + } + + pub fn classes(&self) -> &str { + match &self.0 { Some(classes) => classes.as_str(), None => "", } } pub fn has_classes(&self) -> bool { - self.classes.len() > 0 + self.0 != None } - pub fn option(&mut self) -> &Option { - if !self.updated { - self.option = match self.classes.len() { - 0 => None, - _ => Some(self.classes.join(" ")), - }; - self.updated = true; - } - &self.option + pub fn option(&self) -> &Option { + &self.0 } } diff --git a/pagetop/src/html/optattr.rs b/pagetop/src/html/optattr.rs index af82751c..3eed9aab 100644 --- a/pagetop/src/html/optattr.rs +++ b/pagetop/src/html/optattr.rs @@ -6,11 +6,9 @@ impl OptAttr { } pub fn some(value: &str) -> Self { - let value = value.trim(); - match value.is_empty() { - true => OptAttr(None), - false => OptAttr(Some(value.to_owned())), - } + let mut o = OptAttr::none(); + o.with_value(value); + o } pub fn with_value(&mut self, value: &str) { @@ -29,10 +27,7 @@ impl OptAttr { } pub fn has_value(&self) -> bool { - match &self.0 { - Some(_) => true, - None => false, - } + self.0 != None } pub fn option(&self) -> &Option { diff --git a/pagetop/src/html/optiden.rs b/pagetop/src/html/optiden.rs index ca10155e..93caf18a 100644 --- a/pagetop/src/html/optiden.rs +++ b/pagetop/src/html/optiden.rs @@ -5,6 +5,12 @@ impl OptIden { OptIden(None) } + pub fn some(id: &str) -> Self { + let mut o = OptIden::none(); + o.with_value(id); + o + } + pub fn with_value(&mut self, id: &str) { let id = id.trim(); self.0 = match id.is_empty() { @@ -21,10 +27,7 @@ impl OptIden { } pub fn has_value(&self) -> bool { - match &self.0 { - Some(_) => true, - None => false, - } + self.0 != None } pub fn option(&self) -> &Option { diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 72ab7328..731271d3 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,5 +1,6 @@ // Local. +pub(crate) use concat_string::concat_string; pub(crate) use doc_comment::doc_comment; pub(crate) use once_cell::sync::Lazy; pub(crate) use futures::executor::block_on as run_now; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 5bd4696a..fedf05e4 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -64,7 +64,7 @@ impl<'a> Page<'a> { }, title : OptAttr::none(), description : OptAttr::none(), - body_classes: Classes::some_class("body"), + body_classes: Classes::some(vec!["body"]), assets : PageAssets::new(), regions : COMPONENTS.read().unwrap().clone(), template : "default".to_owned(), @@ -97,12 +97,7 @@ impl<'a> Page<'a> { self } - pub fn add_body_class(&mut self, class: &str) -> &mut Self { - self.body_classes.add_class(class); - self - } - - pub fn add_body_classes(&mut self, classes: Vec) -> &mut Self { + pub fn add_body_classes(&mut self, classes: Vec<&str>) -> &mut Self { self.body_classes.add_classes(classes); self } diff --git a/pagetop/static/bulmix/css/bulma-rtl.min.css b/pagetop/static/bulmix/css/bulma-rtl.min.css new file mode 100644 index 00000000..36fa65bc --- /dev/null +++ b/pagetop/static/bulmix/css/bulma-rtl.min.css @@ -0,0 +1 @@ +/*! bulma.io v0.9.3 | MIT License | github.com/jgthms/bulma */.button,.file-cta,.file-name,.input,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.select select,.textarea{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.5em - 1px);padding-left:calc(.75em - 1px);padding-right:calc(.75em - 1px);padding-top:calc(.5em - 1px);position:relative;vertical-align:top}.button:active,.button:focus,.file-cta:active,.file-cta:focus,.file-name:active,.file-name:focus,.input:active,.input:focus,.is-active.button,.is-active.file-cta,.is-active.file-name,.is-active.input,.is-active.pagination-ellipsis,.is-active.pagination-link,.is-active.pagination-next,.is-active.pagination-previous,.is-active.textarea,.is-focused.button,.is-focused.file-cta,.is-focused.file-name,.is-focused.input,.is-focused.pagination-ellipsis,.is-focused.pagination-link,.is-focused.pagination-next,.is-focused.pagination-previous,.is-focused.textarea,.pagination-ellipsis:active,.pagination-ellipsis:focus,.pagination-link:active,.pagination-link:focus,.pagination-next:active,.pagination-next:focus,.pagination-previous:active,.pagination-previous:focus,.select select.is-active,.select select.is-focused,.select select:active,.select select:focus,.textarea:active,.textarea:focus{outline:0}.button[disabled],.file-cta[disabled],.file-name[disabled],.input[disabled],.pagination-ellipsis[disabled],.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .button,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .input,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-previous,fieldset[disabled] .select select,fieldset[disabled] .textarea{cursor:not-allowed}.breadcrumb,.button,.file,.is-unselectable,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.tabs{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid transparent;border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:.625em;margin-top:-.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:.625em}.block:not(:last-child),.box:not(:last-child),.breadcrumb:not(:last-child),.content:not(:last-child),.level:not(:last-child),.message:not(:last-child),.notification:not(:last-child),.pagination:not(:last-child),.progress:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.tabs:not(:last-child),.title:not(:last-child){margin-bottom:1.5rem}.delete,.modal-close{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:0;position:relative;vertical-align:top;width:20px}.delete::after,.delete::before,.modal-close::after,.modal-close::before{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.delete::before,.modal-close::before{height:2px;width:50%}.delete::after,.modal-close::after{height:50%;width:2px}.delete:focus,.delete:hover,.modal-close:focus,.modal-close:hover{background-color:rgba(10,10,10,.3)}.delete:active,.modal-close:active{background-color:rgba(10,10,10,.4)}.is-small.delete,.is-small.modal-close{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.delete,.is-medium.modal-close{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.delete,.is-large.modal-close{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.button.is-loading::after,.control.is-loading::after,.loader,.select.is-loading::after{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.image.is-16by9 .has-ratio,.image.is-16by9 img,.image.is-1by1 .has-ratio,.image.is-1by1 img,.image.is-1by2 .has-ratio,.image.is-1by2 img,.image.is-1by3 .has-ratio,.image.is-1by3 img,.image.is-2by1 .has-ratio,.image.is-2by1 img,.image.is-2by3 .has-ratio,.image.is-2by3 img,.image.is-3by1 .has-ratio,.image.is-3by1 img,.image.is-3by2 .has-ratio,.image.is-3by2 img,.image.is-3by4 .has-ratio,.image.is-3by4 img,.image.is-3by5 .has-ratio,.image.is-3by5 img,.image.is-4by3 .has-ratio,.image.is-4by3 img,.image.is-4by5 .has-ratio,.image.is-4by5 img,.image.is-5by3 .has-ratio,.image.is-5by3 img,.image.is-5by4 .has-ratio,.image.is-5by4 img,.image.is-9by16 .has-ratio,.image.is-9by16 img,.image.is-square .has-ratio,.image.is-square img,.is-overlay,.modal,.modal-background{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:0 0;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */blockquote,body,dd,dl,dt,fieldset,figure,h1,h2,h3,h4,h5,h6,hr,html,iframe,legend,li,ol,p,pre,textarea,ul{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,::after,::before{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:hidden;overflow-y:scroll;text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:monospace}body{color:#4a4a4a;font-size:1em;font-weight:400;line-height:1.5}a{color:#485fc7;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:#f5f5f5;color:#da1039;font-size:.875em;font-weight:400;padding:.25em .5em .25em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type=checkbox],input[type=radio]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#363636;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#4a4a4a;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#363636}@-webkit-keyframes spinAround{from{transform:rotate(0)}to{transform:rotate(359deg)}}@keyframes spinAround{from{transform:rotate(0)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);color:#4a4a4a;display:block;padding:1.25rem}a.box:focus,a.box:hover{box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px #485fc7}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,.2),0 0 0 1px #485fc7}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#363636;cursor:pointer;justify-content:center;padding-bottom:calc(.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-large,.button .icon.is-medium,.button .icon.is-small{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-right:calc(-.5em - 1px);margin-left:.25em}.button .icon:last-child:not(:first-child){margin-right:.25em;margin-left:calc(-.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-.5em - 1px);margin-right:calc(-.5em - 1px)}.button.is-hovered,.button:hover{border-color:#b5b5b5;color:#363636}.button.is-focused,.button:focus{border-color:#485fc7;color:#363636}.button.is-focused:not(:active),.button:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.button.is-active,.button:active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#4a4a4a;text-decoration:underline}.button.is-text.is-focused,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text:hover{background-color:#f5f5f5;color:#363636}.button.is-text.is-active,.button.is-text:active{background-color:#e8e8e8;color:#363636}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:0 0;border-color:transparent;color:#485fc7;text-decoration:none}.button.is-ghost.is-hovered,.button.is-ghost:hover{color:#485fc7;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white.is-hovered,.button.is-white:hover{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white.is-focused,.button.is-white:focus{border-color:transparent;color:#0a0a0a}.button.is-white.is-focused:not(:active),.button.is-white:focus:not(:active){box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.button.is-white.is-active,.button.is-white:active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:transparent;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-hovered,.button.is-white.is-inverted:hover{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined.is-focused,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-white.is-outlined.is-loading.is-focused::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading:hover::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined.is-focused,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined:hover{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black.is-hovered,.button.is-black:hover{background-color:#040404;border-color:transparent;color:#fff}.button.is-black.is-focused,.button.is-black:focus{border-color:transparent;color:#fff}.button.is-black.is-focused:not(:active),.button.is-black:focus:not(:active){box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.button.is-black.is-active,.button.is-black:active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:transparent;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-hovered,.button.is-black.is-inverted:hover{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined.is-focused,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-black.is-outlined.is-loading.is-focused::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined.is-focused,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined:hover{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-hovered,.button.is-light:hover{background-color:#eee;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-focused,.button.is-light:focus{border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-focused:not(:active),.button.is-light:focus:not(:active){box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.button.is-light.is-active,.button.is-light:active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:transparent;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,.7);color:#f5f5f5}.button.is-light.is-inverted.is-hovered,.button.is-light.is-inverted:hover{background-color:rgba(0,0,0,.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined.is-focused,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined:hover{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-light.is-outlined.is-loading.is-focused::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading:hover::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);color:rgba(0,0,0,.7)}.button.is-light.is-inverted.is-outlined.is-focused,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined:hover{background-color:rgba(0,0,0,.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);box-shadow:none;color:rgba(0,0,0,.7)}.button.is-dark{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark.is-hovered,.button.is-dark:hover{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark.is-focused,.button.is-dark:focus{border-color:transparent;color:#fff}.button.is-dark.is-focused:not(:active),.button.is-dark:focus:not(:active){box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.button.is-dark.is-active,.button.is-dark:active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],fieldset[disabled] .button.is-dark{background-color:#363636;border-color:transparent;box-shadow:none}.button.is-dark.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-hovered,.button.is-dark.is-inverted:hover{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-dark.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined.is-focused,.button.is-dark.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.button.is-dark.is-outlined:hover{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636!important}.button.is-dark.is-outlined.is-loading.is-focused::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-dark.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined.is-focused,.button.is-dark.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined:hover{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #363636 #363636!important}.button.is-dark.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary{background-color:#00d1b2;border-color:transparent;color:#fff}.button.is-primary.is-hovered,.button.is-primary:hover{background-color:#00c4a7;border-color:transparent;color:#fff}.button.is-primary.is-focused,.button.is-primary:focus{border-color:transparent;color:#fff}.button.is-primary.is-focused:not(:active),.button.is-primary:focus:not(:active){box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.button.is-primary.is-active,.button.is-primary:active{background-color:#00b89c;border-color:transparent;color:#fff}.button.is-primary[disabled],fieldset[disabled] .button.is-primary{background-color:#00d1b2;border-color:transparent;box-shadow:none}.button.is-primary.is-inverted{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted.is-hovered,.button.is-primary.is-inverted:hover{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],fieldset[disabled] .button.is-primary.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#00d1b2}.button.is-primary.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-primary.is-outlined{background-color:transparent;border-color:#00d1b2;color:#00d1b2}.button.is-primary.is-outlined.is-focused,.button.is-primary.is-outlined.is-hovered,.button.is-primary.is-outlined:focus,.button.is-primary.is-outlined:hover{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.button.is-primary.is-outlined.is-loading::after{border-color:transparent transparent #00d1b2 #00d1b2!important}.button.is-primary.is-outlined.is-loading.is-focused::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.button.is-primary.is-outlined.is-loading:focus::after,.button.is-primary.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-primary.is-outlined[disabled],fieldset[disabled] .button.is-primary.is-outlined{background-color:transparent;border-color:#00d1b2;box-shadow:none;color:#00d1b2}.button.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined.is-focused,.button.is-primary.is-inverted.is-outlined.is-hovered,.button.is-primary.is-inverted.is-outlined:focus,.button.is-primary.is-inverted.is-outlined:hover{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #00d1b2 #00d1b2!important}.button.is-primary.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light{background-color:#ebfffc;color:#00947e}.button.is-primary.is-light.is-hovered,.button.is-primary.is-light:hover{background-color:#defffa;border-color:transparent;color:#00947e}.button.is-primary.is-light.is-active,.button.is-primary.is-light:active{background-color:#d1fff8;border-color:transparent;color:#00947e}.button.is-link{background-color:#485fc7;border-color:transparent;color:#fff}.button.is-link.is-hovered,.button.is-link:hover{background-color:#3e56c4;border-color:transparent;color:#fff}.button.is-link.is-focused,.button.is-link:focus{border-color:transparent;color:#fff}.button.is-link.is-focused:not(:active),.button.is-link:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.button.is-link.is-active,.button.is-link:active{background-color:#3a51bb;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#485fc7;border-color:transparent;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#485fc7}.button.is-link.is-inverted.is-hovered,.button.is-link.is-inverted:hover{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#485fc7}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-link.is-outlined{background-color:transparent;border-color:#485fc7;color:#485fc7}.button.is-link.is-outlined.is-focused,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined:hover{background-color:#485fc7;border-color:#485fc7;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #485fc7 #485fc7!important}.button.is-link.is-outlined.is-loading.is-focused::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#485fc7;box-shadow:none;color:#485fc7}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined.is-focused,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined:hover{background-color:#fff;color:#485fc7}.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #485fc7 #485fc7!important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff1fa;color:#3850b7}.button.is-link.is-light.is-hovered,.button.is-link.is-light:hover{background-color:#e6e9f7;border-color:transparent;color:#3850b7}.button.is-link.is-light.is-active,.button.is-link.is-light:active{background-color:#dce0f4;border-color:transparent;color:#3850b7}.button.is-info{background-color:#3e8ed0;border-color:transparent;color:#fff}.button.is-info.is-hovered,.button.is-info:hover{background-color:#3488ce;border-color:transparent;color:#fff}.button.is-info.is-focused,.button.is-info:focus{border-color:transparent;color:#fff}.button.is-info.is-focused:not(:active),.button.is-info:focus:not(:active){box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.button.is-info.is-active,.button.is-info:active{background-color:#3082c5;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#3e8ed0;border-color:transparent;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#3e8ed0}.button.is-info.is-inverted.is-hovered,.button.is-info.is-inverted:hover{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#3e8ed0}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-info.is-outlined{background-color:transparent;border-color:#3e8ed0;color:#3e8ed0}.button.is-info.is-outlined.is-focused,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined:hover{background-color:#3e8ed0;border-color:#3e8ed0;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #3e8ed0 #3e8ed0!important}.button.is-info.is-outlined.is-loading.is-focused::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#3e8ed0;box-shadow:none;color:#3e8ed0}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined.is-focused,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined:hover{background-color:#fff;color:#3e8ed0}.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #3e8ed0 #3e8ed0!important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#eff5fb;color:#296fa8}.button.is-info.is-light.is-hovered,.button.is-info.is-light:hover{background-color:#e4eff9;border-color:transparent;color:#296fa8}.button.is-info.is-light.is-active,.button.is-info.is-light:active{background-color:#dae9f6;border-color:transparent;color:#296fa8}.button.is-success{background-color:#48c78e;border-color:transparent;color:#fff}.button.is-success.is-hovered,.button.is-success:hover{background-color:#3ec487;border-color:transparent;color:#fff}.button.is-success.is-focused,.button.is-success:focus{border-color:transparent;color:#fff}.button.is-success.is-focused:not(:active),.button.is-success:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.button.is-success.is-active,.button.is-success:active{background-color:#3abb81;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#48c78e;border-color:transparent;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#48c78e}.button.is-success.is-inverted.is-hovered,.button.is-success.is-inverted:hover{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#48c78e}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-success.is-outlined{background-color:transparent;border-color:#48c78e;color:#48c78e}.button.is-success.is-outlined.is-focused,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined:hover{background-color:#48c78e;border-color:#48c78e;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #48c78e #48c78e!important}.button.is-success.is-outlined.is-loading.is-focused::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#48c78e;box-shadow:none;color:#48c78e}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined.is-focused,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined:hover{background-color:#fff;color:#48c78e}.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #48c78e #48c78e!important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#effaf5;color:#257953}.button.is-success.is-light.is-hovered,.button.is-success.is-light:hover{background-color:#e6f7ef;border-color:transparent;color:#257953}.button.is-success.is-light.is-active,.button.is-success.is-light:active{background-color:#dcf4e9;border-color:transparent;color:#257953}.button.is-warning{background-color:#ffe08a;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-hovered,.button.is-warning:hover{background-color:#ffdc7d;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused,.button.is-warning:focus{border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused:not(:active),.button.is-warning:focus:not(:active){box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.button.is-warning.is-active,.button.is-warning:active{background-color:#ffd970;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffe08a;border-color:transparent;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,.7);color:#ffe08a}.button.is-warning.is-inverted.is-hovered,.button.is-warning.is-inverted:hover{background-color:rgba(0,0,0,.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,.7);border-color:transparent;box-shadow:none;color:#ffe08a}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffe08a;color:#ffe08a}.button.is-warning.is-outlined.is-focused,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined:hover{background-color:#ffe08a;border-color:#ffe08a;color:rgba(0,0,0,.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffe08a #ffe08a!important}.button.is-warning.is-outlined.is-loading.is-focused::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading:hover::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffe08a;box-shadow:none;color:#ffe08a}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);color:rgba(0,0,0,.7)}.button.is-warning.is-inverted.is-outlined.is-focused,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined:hover{background-color:rgba(0,0,0,.7);color:#ffe08a}.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #ffe08a #ffe08a!important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);box-shadow:none;color:rgba(0,0,0,.7)}.button.is-warning.is-light{background-color:#fffaeb;color:#946c00}.button.is-warning.is-light.is-hovered,.button.is-warning.is-light:hover{background-color:#fff6de;border-color:transparent;color:#946c00}.button.is-warning.is-light.is-active,.button.is-warning.is-light:active{background-color:#fff3d1;border-color:transparent;color:#946c00}.button.is-danger{background-color:#f14668;border-color:transparent;color:#fff}.button.is-danger.is-hovered,.button.is-danger:hover{background-color:#f03a5f;border-color:transparent;color:#fff}.button.is-danger.is-focused,.button.is-danger:focus{border-color:transparent;color:#fff}.button.is-danger.is-focused:not(:active),.button.is-danger:focus:not(:active){box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.button.is-danger.is-active,.button.is-danger:active{background-color:#ef2e55;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#f14668;border-color:transparent;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#f14668}.button.is-danger.is-inverted.is-hovered,.button.is-danger.is-inverted:hover{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#f14668}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-danger.is-outlined{background-color:transparent;border-color:#f14668;color:#f14668}.button.is-danger.is-outlined.is-focused,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined:hover{background-color:#f14668;border-color:#f14668;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #f14668 #f14668!important}.button.is-danger.is-outlined.is-loading.is-focused::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#f14668;box-shadow:none;color:#f14668}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined.is-focused,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined:hover{background-color:#fff;color:#f14668}.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #f14668 #f14668!important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#feecf0;color:#cc0f35}.button.is-danger.is-light.is-hovered,.button.is-danger.is-light:hover{background-color:#fde0e6;border-color:transparent;color:#cc0f35}.button.is-danger.is-light.is-active,.button.is-danger.is-light:active{background-color:#fcd4dc;border-color:transparent;color:#cc0f35}.button.is-small{font-size:.75rem}.button.is-small:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent!important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * .5));top:calc(50% - (1em * .5));position:absolute!important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#7a7a7a;box-shadow:none;pointer-events:none}.button.is-rounded{border-radius:9999px;padding-left:calc(1em + .25em);padding-right:calc(1em + .25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-left:.5rem}.buttons:last-child{margin-bottom:-.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-left:-1px}.buttons.has-addons .button:last-child{margin-left:0}.buttons.has-addons .button.is-hovered,.buttons.has-addons .button:hover{z-index:2}.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-focused,.buttons.has-addons .button.is-selected,.buttons.has-addons .button:active,.buttons.has-addons .button:focus{z-index:3}.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button.is-selected:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button:focus:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:.25rem;margin-right:.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:.25rem;margin-right:.25rem}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none!important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width:1024px){.container{max-width:960px}}@media screen and (max-width:1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width:1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width:1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width:1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:.25em}.content blockquote:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content p:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child),.content ul:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#363636;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:.8em}.content h5{font-size:1.125em;margin-bottom:.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-right:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-right:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol:not([type]).is-lower-alpha{list-style-type:lower-alpha}.content ol:not([type]).is-lower-roman{list-style-type:lower-roman}.content ol:not([type]).is-upper-alpha{list-style-type:upper-alpha}.content ol:not([type]).is-upper-roman{list-style-type:upper-roman}.content ul{list-style:disc outside;margin-right:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:.5em}.content ul ul ul{list-style-type:square}.content dd{margin-right:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:1.25em 1.5em;white-space:pre;word-wrap:normal}.content sub,.content sup{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.content table th{color:#363636}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#363636}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#363636}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-left:.25em}.icon-text .icon:not(:first-child){margin-right:.25em}div.icon-text{display:flex}.image{display:block;position:relative}.image img{display:block;height:auto;width:100%}.image img.is-rounded{border-radius:9999px}.image.is-fullwidth{width:100%}.image.is-16by9 .has-ratio,.image.is-16by9 img,.image.is-1by1 .has-ratio,.image.is-1by1 img,.image.is-1by2 .has-ratio,.image.is-1by2 img,.image.is-1by3 .has-ratio,.image.is-1by3 img,.image.is-2by1 .has-ratio,.image.is-2by1 img,.image.is-2by3 .has-ratio,.image.is-2by3 img,.image.is-3by1 .has-ratio,.image.is-3by1 img,.image.is-3by2 .has-ratio,.image.is-3by2 img,.image.is-3by4 .has-ratio,.image.is-3by4 img,.image.is-3by5 .has-ratio,.image.is-3by5 img,.image.is-4by3 .has-ratio,.image.is-4by3 img,.image.is-4by5 .has-ratio,.image.is-4by5 img,.image.is-5by3 .has-ratio,.image.is-5by3 img,.image.is-5by4 .has-ratio,.image.is-5by4 img,.image.is-9by16 .has-ratio,.image.is-9by16 img,.image.is-square .has-ratio,.image.is-square img{height:100%;width:100%}.image.is-1by1,.image.is-square{padding-top:100%}.image.is-5by4{padding-top:80%}.image.is-4by3{padding-top:75%}.image.is-3by2{padding-top:66.6666%}.image.is-5by3{padding-top:60%}.image.is-16by9{padding-top:56.25%}.image.is-2by1{padding-top:50%}.image.is-3by1{padding-top:33.3333%}.image.is-4by5{padding-top:125%}.image.is-3by4{padding-top:133.3333%}.image.is-2by3{padding-top:150%}.image.is-3by5{padding-top:166.6666%}.image.is-9by16{padding-top:177.7777%}.image.is-1by2{padding-top:200%}.image.is-1by3{padding-top:300%}.image.is-16x16{height:16px;width:16px}.image.is-24x24{height:24px;width:24px}.image.is-32x32{height:32px;width:32px}.image.is-48x48{height:48px;width:48px}.image.is-64x64{height:64px;width:64px}.image.is-96x96{height:96px;width:96px}.image.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 1.5rem 1.25rem 2.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:0 0}.notification>.delete{left:.5rem;position:absolute;top:.5rem}.notification .content,.notification .subtitle,.notification .title{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.notification.is-dark{background-color:#363636;color:#fff}.notification.is-primary{background-color:#00d1b2;color:#fff}.notification.is-primary.is-light{background-color:#ebfffc;color:#00947e}.notification.is-link{background-color:#485fc7;color:#fff}.notification.is-link.is-light{background-color:#eff1fa;color:#3850b7}.notification.is-info{background-color:#3e8ed0;color:#fff}.notification.is-info.is-light{background-color:#eff5fb;color:#296fa8}.notification.is-success{background-color:#48c78e;color:#fff}.notification.is-success.is-light{background-color:#effaf5;color:#257953}.notification.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.notification.is-warning.is-light{background-color:#fffaeb;color:#946c00}.notification.is-danger{background-color:#f14668;color:#fff}.notification.is-danger.is-light{background-color:#feecf0;color:#cc0f35}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#4a4a4a}.progress::-moz-progress-bar{background-color:#4a4a4a}.progress::-ms-fill{background-color:#4a4a4a;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right,#fff 30%,#ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right,#0a0a0a 30%,#ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right,#f5f5f5 30%,#ededed 30%)}.progress.is-dark::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate{background-image:linear-gradient(to right,#363636 30%,#ededed 30%)}.progress.is-primary::-webkit-progress-value{background-color:#00d1b2}.progress.is-primary::-moz-progress-bar{background-color:#00d1b2}.progress.is-primary::-ms-fill{background-color:#00d1b2}.progress.is-primary:indeterminate{background-image:linear-gradient(to right,#00d1b2 30%,#ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#485fc7}.progress.is-link::-moz-progress-bar{background-color:#485fc7}.progress.is-link::-ms-fill{background-color:#485fc7}.progress.is-link:indeterminate{background-image:linear-gradient(to right,#485fc7 30%,#ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#3e8ed0}.progress.is-info::-moz-progress-bar{background-color:#3e8ed0}.progress.is-info::-ms-fill{background-color:#3e8ed0}.progress.is-info:indeterminate{background-image:linear-gradient(to right,#3e8ed0 30%,#ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#48c78e}.progress.is-success::-moz-progress-bar{background-color:#48c78e}.progress.is-success::-ms-fill{background-color:#48c78e}.progress.is-success:indeterminate{background-image:linear-gradient(to right,#48c78e 30%,#ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffe08a}.progress.is-warning::-moz-progress-bar{background-color:#ffe08a}.progress.is-warning::-ms-fill{background-color:#ffe08a}.progress.is-warning:indeterminate{background-image:linear-gradient(to right,#ffe08a 30%,#ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#f14668}.progress.is-danger::-moz-progress-bar{background-color:#f14668}.progress.is-danger::-ms-fill{background-color:#f14668}.progress.is-danger:indeterminate{background-image:linear-gradient(to right,#f14668 30%,#ededed 30%)}.progress:indeterminate{-webkit-animation-duration:1.5s;animation-duration:1.5s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:moveIndeterminate;animation-name:moveIndeterminate;-webkit-animation-timing-function:linear;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right,#4a4a4a 30%,#ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@-webkit-keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#363636}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.table td.is-link,.table th.is-link{background-color:#485fc7;border-color:#485fc7;color:#fff}.table td.is-info,.table th.is-info{background-color:#3e8ed0;border-color:#3e8ed0;color:#fff}.table td.is-success,.table th.is-success{background-color:#48c78e;border-color:#48c78e;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffe08a;border-color:#ffe08a;color:rgba(0,0,0,.7)}.table td.is-danger,.table th.is-danger{background-color:#f14668;border-color:#f14668;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#00d1b2;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#363636}.table th:not([align]){text-align:inherit}.table tr.is-selected{background-color:#00d1b2;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:transparent}.table thead td,.table thead th{border-width:0 0 2px;color:#363636}.table tfoot{background-color:transparent}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#363636}.table tbody{background-color:transparent}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:.25em .5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag{margin-bottom:.5rem}.tags .tag:not(:last-child){margin-left:.5rem}.tags:last-child{margin-bottom:-.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag{margin-right:.25rem;margin-left:.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child){margin-left:.5rem}.tags.is-right .tag:not(:last-child){margin-right:0}.tags.has-addons .tag{margin-left:0}.tags.has-addons .tag:not(:first-child){margin-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.tags.has-addons .tag:not(:last-child){border-top-left-radius:0;border-bottom-left-radius:0}.tag:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#4a4a4a;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:.75em;padding-right:.75em;white-space:nowrap}.tag:not(body) .delete{margin-right:.25rem;margin-left:-.375rem}.tag:not(body).is-white{background-color:#fff;color:#0a0a0a}.tag:not(body).is-black{background-color:#0a0a0a;color:#fff}.tag:not(body).is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.tag:not(body).is-dark{background-color:#363636;color:#fff}.tag:not(body).is-primary{background-color:#00d1b2;color:#fff}.tag:not(body).is-primary.is-light{background-color:#ebfffc;color:#00947e}.tag:not(body).is-link{background-color:#485fc7;color:#fff}.tag:not(body).is-link.is-light{background-color:#eff1fa;color:#3850b7}.tag:not(body).is-info{background-color:#3e8ed0;color:#fff}.tag:not(body).is-info.is-light{background-color:#eff5fb;color:#296fa8}.tag:not(body).is-success{background-color:#48c78e;color:#fff}.tag:not(body).is-success.is-light{background-color:#effaf5;color:#257953}.tag:not(body).is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.tag:not(body).is-warning.is-light{background-color:#fffaeb;color:#946c00}.tag:not(body).is-danger{background-color:#f14668;color:#fff}.tag:not(body).is-danger.is-light{background-color:#feecf0;color:#cc0f35}.tag:not(body).is-normal{font-size:.75rem}.tag:not(body).is-medium{font-size:1rem}.tag:not(body).is-large{font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child){margin-right:-.375em;margin-left:.1875em}.tag:not(body) .icon:last-child:not(:first-child){margin-right:.1875em;margin-left:-.375em}.tag:not(body) .icon:first-child:last-child{margin-right:-.375em;margin-left:-.375em}.tag:not(body).is-delete{margin-right:1px;padding:0;position:relative;width:2em}.tag:not(body).is-delete::after,.tag:not(body).is-delete::before{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag:not(body).is-delete::before{height:1px;width:50%}.tag:not(body).is-delete::after{height:50%;width:1px}.tag:not(body).is-delete:focus,.tag:not(body).is-delete:hover{background-color:#e8e8e8}.tag:not(body).is-delete:active{background-color:#dbdbdb}.tag:not(body).is-rounded{border-radius:9999px}a.tag:hover{text-decoration:underline}.subtitle,.title{word-break:break-word}.subtitle em,.subtitle span,.title em,.title span{font-weight:inherit}.subtitle sub,.title sub{font-size:.75em}.subtitle sup,.title sup{font-size:.75em}.subtitle .tag,.title .tag{vertical-align:middle}.title{color:#363636;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#4a4a4a;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#363636;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:.25rem .5rem;text-align:center;vertical-align:top}.input,.select select,.textarea{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.input::-moz-placeholder,.select select::-moz-placeholder,.textarea::-moz-placeholder{color:rgba(54,54,54,.3)}.input::-webkit-input-placeholder,.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.input:-moz-placeholder,.select select:-moz-placeholder,.textarea:-moz-placeholder{color:rgba(54,54,54,.3)}.input:-ms-input-placeholder,.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:rgba(54,54,54,.3)}.input:hover,.is-hovered.input,.is-hovered.textarea,.select select.is-hovered,.select select:hover,.textarea:hover{border-color:#b5b5b5}.input:active,.input:focus,.is-active.input,.is-active.textarea,.is-focused.input,.is-focused.textarea,.select select.is-active,.select select.is-focused,.select select:active,.select select:focus,.textarea:active,.textarea:focus{border-color:#485fc7;box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.input[disabled]::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder{color:rgba(122,122,122,.3)}.input,.textarea{box-shadow:inset 0 .0625em .125em rgba(10,10,10,.05);max-width:100%;width:100%}.input[readonly],.textarea[readonly]{box-shadow:none}.is-white.input,.is-white.textarea{border-color:#fff}.is-white.input:active,.is-white.input:focus,.is-white.is-active.input,.is-white.is-active.textarea,.is-white.is-focused.input,.is-white.is-focused.textarea,.is-white.textarea:active,.is-white.textarea:focus{box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.is-black.input,.is-black.textarea{border-color:#0a0a0a}.is-black.input:active,.is-black.input:focus,.is-black.is-active.input,.is-black.is-active.textarea,.is-black.is-focused.input,.is-black.is-focused.textarea,.is-black.textarea:active,.is-black.textarea:focus{box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.is-light.input,.is-light.textarea{border-color:#f5f5f5}.is-light.input:active,.is-light.input:focus,.is-light.is-active.input,.is-light.is-active.textarea,.is-light.is-focused.input,.is-light.is-focused.textarea,.is-light.textarea:active,.is-light.textarea:focus{box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.is-dark.input,.is-dark.textarea{border-color:#363636}.is-dark.input:active,.is-dark.input:focus,.is-dark.is-active.input,.is-dark.is-active.textarea,.is-dark.is-focused.input,.is-dark.is-focused.textarea,.is-dark.textarea:active,.is-dark.textarea:focus{box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.is-primary.input,.is-primary.textarea{border-color:#00d1b2}.is-primary.input:active,.is-primary.input:focus,.is-primary.is-active.input,.is-primary.is-active.textarea,.is-primary.is-focused.input,.is-primary.is-focused.textarea,.is-primary.textarea:active,.is-primary.textarea:focus{box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.is-link.input,.is-link.textarea{border-color:#485fc7}.is-link.input:active,.is-link.input:focus,.is-link.is-active.input,.is-link.is-active.textarea,.is-link.is-focused.input,.is-link.is-focused.textarea,.is-link.textarea:active,.is-link.textarea:focus{box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.is-info.input,.is-info.textarea{border-color:#3e8ed0}.is-info.input:active,.is-info.input:focus,.is-info.is-active.input,.is-info.is-active.textarea,.is-info.is-focused.input,.is-info.is-focused.textarea,.is-info.textarea:active,.is-info.textarea:focus{box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.is-success.input,.is-success.textarea{border-color:#48c78e}.is-success.input:active,.is-success.input:focus,.is-success.is-active.input,.is-success.is-active.textarea,.is-success.is-focused.input,.is-success.is-focused.textarea,.is-success.textarea:active,.is-success.textarea:focus{box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.is-warning.input,.is-warning.textarea{border-color:#ffe08a}.is-warning.input:active,.is-warning.input:focus,.is-warning.is-active.input,.is-warning.is-active.textarea,.is-warning.is-focused.input,.is-warning.is-focused.textarea,.is-warning.textarea:active,.is-warning.textarea:focus{box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.is-danger.input,.is-danger.textarea{border-color:#f14668}.is-danger.input:active,.is-danger.input:focus,.is-danger.is-active.input,.is-danger.is-active.textarea,.is-danger.is-focused.input,.is-danger.is-focused.textarea,.is-danger.textarea:active,.is-danger.textarea:focus{box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.is-small.input,.is-small.textarea{border-radius:2px;font-size:.75rem}.is-medium.input,.is-medium.textarea{font-size:1.25rem}.is-large.input,.is-large.textarea{font-size:1.5rem}.is-fullwidth.input,.is-fullwidth.textarea{display:block;width:100%}.is-inline.input,.is-inline.textarea{display:inline;width:auto}.input.is-rounded{border-radius:9999px;padding-left:calc(calc(.75em - 1px) + .375em);padding-right:calc(calc(.75em - 1px) + .375em)}.input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.checkbox,.radio{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.checkbox input,.radio input{cursor:pointer}.checkbox:hover,.radio:hover{color:#363636}.checkbox input[disabled],.checkbox[disabled],.radio input[disabled],.radio[disabled],fieldset[disabled] .checkbox,fieldset[disabled] .radio{color:#7a7a7a;cursor:not-allowed}.radio+.radio{margin-right:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#485fc7;left:1.125em;z-index:4}.select.is-rounded select{border-radius:9999px;padding-right:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:0}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-left:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#363636}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select.is-hovered,.select.is-white select:hover{border-color:#f2f2f2}.select.is-white select.is-active,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select:focus{box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select.is-hovered,.select.is-black select:hover{border-color:#000}.select.is-black select.is-active,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select:focus{box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select.is-hovered,.select.is-light select:hover{border-color:#e8e8e8}.select.is-light select.is-active,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select:focus{box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.select.is-dark:not(:hover)::after{border-color:#363636}.select.is-dark select{border-color:#363636}.select.is-dark select.is-hovered,.select.is-dark select:hover{border-color:#292929}.select.is-dark select.is-active,.select.is-dark select.is-focused,.select.is-dark select:active,.select.is-dark select:focus{box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.select.is-primary:not(:hover)::after{border-color:#00d1b2}.select.is-primary select{border-color:#00d1b2}.select.is-primary select.is-hovered,.select.is-primary select:hover{border-color:#00b89c}.select.is-primary select.is-active,.select.is-primary select.is-focused,.select.is-primary select:active,.select.is-primary select:focus{box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.select.is-link:not(:hover)::after{border-color:#485fc7}.select.is-link select{border-color:#485fc7}.select.is-link select.is-hovered,.select.is-link select:hover{border-color:#3a51bb}.select.is-link select.is-active,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select:focus{box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.select.is-info:not(:hover)::after{border-color:#3e8ed0}.select.is-info select{border-color:#3e8ed0}.select.is-info select.is-hovered,.select.is-info select:hover{border-color:#3082c5}.select.is-info select.is-active,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select:focus{box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.select.is-success:not(:hover)::after{border-color:#48c78e}.select.is-success select{border-color:#48c78e}.select.is-success select.is-hovered,.select.is-success select:hover{border-color:#3abb81}.select.is-success select.is-active,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select:focus{box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.select.is-warning:not(:hover)::after{border-color:#ffe08a}.select.is-warning select{border-color:#ffe08a}.select.is-warning select.is-hovered,.select.is-warning select:hover{border-color:#ffd970}.select.is-warning select.is-active,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select:focus{box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.select.is-danger:not(:hover)::after{border-color:#f14668}.select.is-danger select{border-color:#f14668}.select.is-danger select.is-hovered,.select.is-danger select:hover{border-color:#ef2e55}.select.is-danger select.is-active,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select:focus{box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.select.is-small{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#7a7a7a}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;left:.625em;top:.625em;transform:none}.select.is-loading.is-small:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white.is-hovered .file-cta,.file.is-white:hover .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white.is-focused .file-cta,.file.is-white:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(255,255,255,.25);color:#0a0a0a}.file.is-white.is-active .file-cta,.file.is-white:active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black.is-hovered .file-cta,.file.is-black:hover .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black.is-focused .file-cta,.file.is-black:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(10,10,10,.25);color:#fff}.file.is-black.is-active .file-cta,.file.is-black:active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-light.is-hovered .file-cta,.file.is-light:hover .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-light.is-focused .file-cta,.file.is-light:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(245,245,245,.25);color:rgba(0,0,0,.7)}.file.is-light.is-active .file-cta,.file.is-light:active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-dark .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark.is-hovered .file-cta,.file.is-dark:hover .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark.is-focused .file-cta,.file.is-dark:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(54,54,54,.25);color:#fff}.file.is-dark.is-active .file-cta,.file.is-dark:active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta{background-color:#00d1b2;border-color:transparent;color:#fff}.file.is-primary.is-hovered .file-cta,.file.is-primary:hover .file-cta{background-color:#00c4a7;border-color:transparent;color:#fff}.file.is-primary.is-focused .file-cta,.file.is-primary:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(0,209,178,.25);color:#fff}.file.is-primary.is-active .file-cta,.file.is-primary:active .file-cta{background-color:#00b89c;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#485fc7;border-color:transparent;color:#fff}.file.is-link.is-hovered .file-cta,.file.is-link:hover .file-cta{background-color:#3e56c4;border-color:transparent;color:#fff}.file.is-link.is-focused .file-cta,.file.is-link:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(72,95,199,.25);color:#fff}.file.is-link.is-active .file-cta,.file.is-link:active .file-cta{background-color:#3a51bb;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#3e8ed0;border-color:transparent;color:#fff}.file.is-info.is-hovered .file-cta,.file.is-info:hover .file-cta{background-color:#3488ce;border-color:transparent;color:#fff}.file.is-info.is-focused .file-cta,.file.is-info:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(62,142,208,.25);color:#fff}.file.is-info.is-active .file-cta,.file.is-info:active .file-cta{background-color:#3082c5;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#48c78e;border-color:transparent;color:#fff}.file.is-success.is-hovered .file-cta,.file.is-success:hover .file-cta{background-color:#3ec487;border-color:transparent;color:#fff}.file.is-success.is-focused .file-cta,.file.is-success:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(72,199,142,.25);color:#fff}.file.is-success.is-active .file-cta,.file.is-success:active .file-cta{background-color:#3abb81;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffe08a;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-hovered .file-cta,.file.is-warning:hover .file-cta{background-color:#ffdc7d;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-focused .file-cta,.file.is-warning:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(255,224,138,.25);color:rgba(0,0,0,.7)}.file.is-warning.is-active .file-cta,.file.is-warning:active .file-cta{background-color:#ffd970;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-danger .file-cta{background-color:#f14668;border-color:transparent;color:#fff}.file.is-danger.is-hovered .file-cta,.file.is-danger:hover .file-cta{background-color:#f03a5f;border-color:transparent;color:#fff}.file.is-danger.is-focused .file-cta,.file.is-danger:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(241,70,104,.25);color:#fff}.file.is-danger.is-active .file-cta,.file.is-danger:active .file-cta{background-color:#ef2e55;border-color:transparent;color:#fff}.file.is-small{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#363636}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#363636}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:0;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#4a4a4a}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-left:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#363636;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:.5em}.label.is-small{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark{color:#363636}.help.is-primary{color:#00d1b2}.help.is-link{color:#485fc7}.help.is-info{color:#3e8ed0}.help.is-success{color:#48c78e}.help.is-warning{color:#ffe08a}.help.is-danger{color:#f14668}.field:not(:last-child){margin-bottom:.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-left:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control .button:not([disabled]).is-hovered,.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .input:not([disabled]).is-hovered,.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]).is-hovered,.field.has-addons .control .select select:not([disabled]):hover{z-index:2}.field.has-addons .control .button:not([disabled]).is-active,.field.has-addons .control .button:not([disabled]).is-focused,.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .input:not([disabled]).is-active,.field.has-addons .control .input:not([disabled]).is-focused,.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control .select select:not([disabled]).is-active,.field.has-addons .control .select select:not([disabled]).is-focused,.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select:not([disabled]):focus{z-index:3}.field.has-addons .control .button:not([disabled]).is-active:hover,.field.has-addons .control .button:not([disabled]).is-focused:hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .input:not([disabled]).is-active:hover,.field.has-addons .control .input:not([disabled]).is-focused:hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control .select select:not([disabled]).is-active:hover,.field.has-addons .control .select select:not([disabled]).is-focused:hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select:not([disabled]):focus:hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-left:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width:769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width:768px){.field-label{margin-bottom:.5rem}}@media screen and (min-width:769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-left:1.5rem;text-align:right}.field-label.is-small{font-size:.75rem;padding-top:.375em}.field-label.is-normal{padding-top:.375em}.field-label.is-medium{font-size:1.25rem;padding-top:.375em}.field-label.is-large{font-size:1.5rem;padding-top:.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width:769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-left:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#4a4a4a}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute!important;left:.625em;top:.625em;z-index:4}.control.is-loading.is-small:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#485fc7;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-right:0}.breadcrumb li.is-active a{color:#363636;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ol,.breadcrumb ul{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-left:.5em}.breadcrumb .icon:last-child{margin-right:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);color:#4a4a4a;max-width:100%;position:relative}.card-content:first-child,.card-footer:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-content:last-child,.card-footer:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:transparent;align-items:stretch;box-shadow:0 .125em .25em rgba(10,10,10,.1);display:flex}.card-header-title{align-items:center;color:#363636;display:flex;flex-grow:1;font-weight:700;padding:.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:0 0;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:transparent;padding:1.5rem}.card-footer{background-color:transparent;border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-left:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;right:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-left:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#485fc7;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-left:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width:769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .subtitle,.level-item .title{margin-bottom:0}@media screen and (max-width:768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width:769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-left:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width:768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width:769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width:769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-left:1rem}.media-right{margin-right:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width:768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#4a4a4a;display:block;padding:.5em .75em}.menu-list a:hover{background-color:#f5f5f5;color:#363636}.menu-list a.is-active{background-color:#485fc7;color:#fff}.menu-list li ul{border-right:1px solid #dbdbdb;margin:.75em;padding-right:.75em}.menu-label{color:#7a7a7a;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark{background-color:#fafafa}.message.is-dark .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body{border-color:#363636}.message.is-primary{background-color:#ebfffc}.message.is-primary .message-header{background-color:#00d1b2;color:#fff}.message.is-primary .message-body{border-color:#00d1b2;color:#00947e}.message.is-link{background-color:#eff1fa}.message.is-link .message-header{background-color:#485fc7;color:#fff}.message.is-link .message-body{border-color:#485fc7;color:#3850b7}.message.is-info{background-color:#eff5fb}.message.is-info .message-header{background-color:#3e8ed0;color:#fff}.message.is-info .message-body{border-color:#3e8ed0;color:#296fa8}.message.is-success{background-color:#effaf5}.message.is-success .message-header{background-color:#48c78e;color:#fff}.message.is-success .message-body{border-color:#48c78e;color:#257953}.message.is-warning{background-color:#fffaeb}.message.is-warning .message-header{background-color:#ffe08a;color:rgba(0,0,0,.7)}.message.is-warning .message-body{border-color:#ffe08a;color:#946c00}.message.is-danger{background-color:#feecf0}.message.is-danger .message-header{background-color:#f14668;color:#fff}.message.is-danger .message-body{border-color:#f14668;color:#cc0f35}.message-header{align-items:center;background-color:#4a4a4a;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-right:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#4a4a4a;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:transparent}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,.86)}.modal-card,.modal-content{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width:769px){.modal-card,.modal-content{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:0 0;height:40px;position:fixed;left:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-foot,.modal-card-head{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#363636;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-left:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link,.navbar.is-white .navbar-brand>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width:1024px){.navbar.is-white .navbar-end .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-start>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link::after,.navbar.is-white .navbar-start .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand .navbar-link,.navbar.is-black .navbar-brand>.navbar-item{color:#fff}.navbar.is-black .navbar-brand .navbar-link.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-black .navbar-end .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-start>.navbar-item{color:#fff}.navbar.is-black .navbar-end .navbar-link.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-end .navbar-link::after,.navbar.is-black .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link,.navbar.is-light .navbar-brand>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,.7)}@media screen and (min-width:1024px){.navbar.is-light .navbar-end .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-start>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-light .navbar-end .navbar-link.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-end .navbar-link::after,.navbar.is-light .navbar-start .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,.7)}}.navbar.is-dark{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand .navbar-link,.navbar.is-dark .navbar-brand>.navbar-item{color:#fff}.navbar.is-dark .navbar-brand .navbar-link.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-dark .navbar-end .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.navbar.is-dark .navbar-start>.navbar-item{color:#fff}.navbar.is-dark .navbar-end .navbar-link.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover{background-color:#292929;color:#fff}.navbar.is-dark .navbar-end .navbar-link::after,.navbar.is-dark .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary{background-color:#00d1b2;color:#fff}.navbar.is-primary .navbar-brand .navbar-link,.navbar.is-primary .navbar-brand>.navbar-item{color:#fff}.navbar.is-primary .navbar-brand .navbar-link.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-primary .navbar-end .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.navbar.is-primary .navbar-start>.navbar-item{color:#fff}.navbar.is-primary .navbar-end .navbar-link.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-end .navbar-link::after,.navbar.is-primary .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active{background-color:#00d1b2;color:#fff}}.navbar.is-link{background-color:#485fc7;color:#fff}.navbar.is-link .navbar-brand .navbar-link,.navbar.is-link .navbar-brand>.navbar-item{color:#fff}.navbar.is-link .navbar-brand .navbar-link.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-link .navbar-end .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-start>.navbar-item{color:#fff}.navbar.is-link .navbar-end .navbar-link.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-end .navbar-link::after,.navbar.is-link .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#485fc7;color:#fff}}.navbar.is-info{background-color:#3e8ed0;color:#fff}.navbar.is-info .navbar-brand .navbar-link,.navbar.is-info .navbar-brand>.navbar-item{color:#fff}.navbar.is-info .navbar-brand .navbar-link.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-info .navbar-end .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-start>.navbar-item{color:#fff}.navbar.is-info .navbar-end .navbar-link.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-end .navbar-link::after,.navbar.is-info .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#3e8ed0;color:#fff}}.navbar.is-success{background-color:#48c78e;color:#fff}.navbar.is-success .navbar-brand .navbar-link,.navbar.is-success .navbar-brand>.navbar-item{color:#fff}.navbar.is-success .navbar-brand .navbar-link.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-success .navbar-end .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-start>.navbar-item{color:#fff}.navbar.is-success .navbar-end .navbar-link.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-end .navbar-link::after,.navbar.is-success .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#48c78e;color:#fff}}.navbar.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link,.navbar.is-warning .navbar-brand>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,.7)}@media screen and (min-width:1024px){.navbar.is-warning .navbar-end .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-start>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link::after,.navbar.is-warning .navbar-start .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffe08a;color:rgba(0,0,0,.7)}}.navbar.is-danger{background-color:#f14668;color:#fff}.navbar.is-danger .navbar-brand .navbar-link,.navbar.is-danger .navbar-brand>.navbar-item{color:#fff}.navbar.is-danger .navbar-brand .navbar-link.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-danger .navbar-end .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-start>.navbar-item{color:#fff}.navbar.is-danger .navbar-end .navbar-link.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-end .navbar-link::after,.navbar.is-danger .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#f14668;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}body.has-navbar-fixed-top,html.has-navbar-fixed-top{padding-top:3.25rem}body.has-navbar-fixed-bottom,html.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#4a4a4a;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-right:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color,opacity,transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#4a4a4a;display:block;line-height:1.5;padding:.5rem .75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-.25rem;margin-right:-.25rem}.navbar-link,a.navbar-item{cursor:pointer}.navbar-link.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,a.navbar-item.is-active,a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover{background-color:#fafafa;color:#485fc7}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:transparent;border-bottom-color:#485fc7}.navbar-item.is-tab.is-active{background-color:transparent;border-bottom-color:#485fc7;border-bottom-style:solid;border-bottom-width:3px;color:#485fc7;padding-bottom:calc(.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-left:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#485fc7;margin-top:-.375em;left:1.125em}.navbar-dropdown{font-size:.875rem;padding-bottom:.5rem;padding-top:.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:.5rem 0}@media screen and (max-width:1023px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,.1);padding:.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}body.has-navbar-fixed-top-touch,html.has-navbar-fixed-top-touch{padding-top:3.25rem}body.has-navbar-fixed-bottom-touch,html.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width:1024px){.navbar,.navbar-end,.navbar-menu,.navbar-start{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-end,.navbar.is-spaced .navbar-start{align-items:center}.navbar.is-spaced .navbar-link,.navbar.is-spaced a.navbar-item{border-radius:4px}.navbar.is-transparent .navbar-link.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover{background-color:transparent!important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent!important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#485fc7}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(.25em,-.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-left:auto}.navbar-end{justify-content:flex-end;margin-right:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,.1);display:none;font-size:.875rem;right:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-left:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#485fc7}.navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-dropdown{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity,transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.container>.navbar .navbar-brand,.navbar>.container .navbar-brand{margin-right:-.75rem}.container>.navbar .navbar-menu,.navbar>.container .navbar-menu{margin-left:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-desktop{top:0}body.has-navbar-fixed-top-desktop,html.has-navbar-fixed-top-desktop{padding-top:3.25rem}body.has-navbar-fixed-bottom-desktop,html.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}body.has-spaced-navbar-fixed-top,html.has-spaced-navbar-fixed-top{padding-top:5.25rem}body.has-spaced-navbar-fixed-bottom,html.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}.navbar-link.is-active,a.navbar-item.is-active{color:#0a0a0a}.navbar-link.is-active:not(:focus):not(:hover),a.navbar-item.is-active:not(:focus):not(:hover){background-color:transparent}.navbar-item.has-dropdown.is-active .navbar-link,.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-next,.pagination.is-rounded .pagination-previous{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-link,.pagination-next,.pagination-previous{border-color:#dbdbdb;color:#363636;min-width:2.5em}.pagination-link:hover,.pagination-next:hover,.pagination-previous:hover{border-color:#b5b5b5;color:#363636}.pagination-link:focus,.pagination-next:focus,.pagination-previous:focus{border-color:#485fc7}.pagination-link:active,.pagination-next:active,.pagination-previous:active{box-shadow:inset 0 1px 2px rgba(10,10,10,.2)}.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled]{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#7a7a7a;opacity:.5}.pagination-next,.pagination-previous{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#485fc7;border-color:#485fc7;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width:768px){.pagination{flex-wrap:wrap}.pagination-next,.pagination-previous{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width:769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading{background-color:#00d1b2;color:#fff}.panel.is-primary .panel-tabs a.is-active{border-bottom-color:#00d1b2}.panel.is-primary .panel-block.is-active .panel-icon{color:#00d1b2}.panel.is-link .panel-heading{background-color:#485fc7;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#485fc7}.panel.is-link .panel-block.is-active .panel-icon{color:#485fc7}.panel.is-info .panel-heading{background-color:#3e8ed0;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#3e8ed0}.panel.is-info .panel-block.is-active .panel-icon{color:#3e8ed0}.panel.is-success .panel-heading{background-color:#48c78e;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#48c78e}.panel.is-success .panel-block.is-active .panel-icon{color:#48c78e}.panel.is-warning .panel-heading{background-color:#ffe08a;color:rgba(0,0,0,.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffe08a}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffe08a}.panel.is-danger .panel-heading{background-color:#f14668;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#f14668}.panel.is-danger .panel-block.is-active .panel-icon{color:#f14668}.panel-block:not(:last-child),.panel-tabs:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#363636;font-size:1.25em;font-weight:700;line-height:1.25;padding:.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#4a4a4a}.panel-list a:hover{color:#485fc7}.panel-block{align-items:center;color:#363636;display:flex;justify-content:flex-start;padding:.5em .75em}.panel-block input[type=checkbox]{margin-left:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#485fc7;color:#363636}.panel-block.is-active .panel-icon{color:#485fc7}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#7a7a7a;margin-left:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#4a4a4a;display:flex;justify-content:center;margin-bottom:-1px;padding:.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#363636;color:#363636}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#485fc7;color:#485fc7}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:.75em;padding-right:.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:.75em}.tabs .icon:first-child{margin-left:.5em}.tabs .icon:last-child{margin-right:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:0 0 4px 4px}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:transparent!important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-right:-1px}.tabs.is-toggle li:first-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li:last-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li.is-active a{background-color:#485fc7;border-color:#485fc7;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-small{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-right:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-right:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-right:50%}.columns.is-mobile>.column.is-offset-one-third{margin-right:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-right:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-right:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-right:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-right:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-right:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-right:0}.columns.is-mobile>.column.is-1{flex:none;width:8.33333%}.columns.is-mobile>.column.is-offset-1{margin-right:8.33333%}.columns.is-mobile>.column.is-2{flex:none;width:16.66667%}.columns.is-mobile>.column.is-offset-2{margin-right:16.66667%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-right:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333%}.columns.is-mobile>.column.is-offset-4{margin-right:33.33333%}.columns.is-mobile>.column.is-5{flex:none;width:41.66667%}.columns.is-mobile>.column.is-offset-5{margin-right:41.66667%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-right:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333%}.columns.is-mobile>.column.is-offset-7{margin-right:58.33333%}.columns.is-mobile>.column.is-8{flex:none;width:66.66667%}.columns.is-mobile>.column.is-offset-8{margin-right:66.66667%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-right:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333%}.columns.is-mobile>.column.is-offset-10{margin-right:83.33333%}.columns.is-mobile>.column.is-11{flex:none;width:91.66667%}.columns.is-mobile>.column.is-offset-11{margin-right:91.66667%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-right:100%}@media screen and (max-width:768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-right:75%}.column.is-offset-two-thirds-mobile{margin-right:66.6666%}.column.is-offset-half-mobile{margin-right:50%}.column.is-offset-one-third-mobile{margin-right:33.3333%}.column.is-offset-one-quarter-mobile{margin-right:25%}.column.is-offset-one-fifth-mobile{margin-right:20%}.column.is-offset-two-fifths-mobile{margin-right:40%}.column.is-offset-three-fifths-mobile{margin-right:60%}.column.is-offset-four-fifths-mobile{margin-right:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-right:0}.column.is-1-mobile{flex:none;width:8.33333%}.column.is-offset-1-mobile{margin-right:8.33333%}.column.is-2-mobile{flex:none;width:16.66667%}.column.is-offset-2-mobile{margin-right:16.66667%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-right:25%}.column.is-4-mobile{flex:none;width:33.33333%}.column.is-offset-4-mobile{margin-right:33.33333%}.column.is-5-mobile{flex:none;width:41.66667%}.column.is-offset-5-mobile{margin-right:41.66667%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-right:50%}.column.is-7-mobile{flex:none;width:58.33333%}.column.is-offset-7-mobile{margin-right:58.33333%}.column.is-8-mobile{flex:none;width:66.66667%}.column.is-offset-8-mobile{margin-right:66.66667%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-right:75%}.column.is-10-mobile{flex:none;width:83.33333%}.column.is-offset-10-mobile{margin-right:83.33333%}.column.is-11-mobile{flex:none;width:91.66667%}.column.is-offset-11-mobile{margin-right:91.66667%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-right:100%}}@media screen and (min-width:769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-right:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-right:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-right:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-right:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-right:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-right:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-right:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-right:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-right:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-right:0}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333%}.column.is-offset-1,.column.is-offset-1-tablet{margin-right:8.33333%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66667%}.column.is-offset-2,.column.is-offset-2-tablet{margin-right:16.66667%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-right:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333%}.column.is-offset-4,.column.is-offset-4-tablet{margin-right:33.33333%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66667%}.column.is-offset-5,.column.is-offset-5-tablet{margin-right:41.66667%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-right:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333%}.column.is-offset-7,.column.is-offset-7-tablet{margin-right:58.33333%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66667%}.column.is-offset-8,.column.is-offset-8-tablet{margin-right:66.66667%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-right:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333%}.column.is-offset-10,.column.is-offset-10-tablet{margin-right:83.33333%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66667%}.column.is-offset-11,.column.is-offset-11-tablet{margin-right:91.66667%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-right:100%}}@media screen and (max-width:1023px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-right:75%}.column.is-offset-two-thirds-touch{margin-right:66.6666%}.column.is-offset-half-touch{margin-right:50%}.column.is-offset-one-third-touch{margin-right:33.3333%}.column.is-offset-one-quarter-touch{margin-right:25%}.column.is-offset-one-fifth-touch{margin-right:20%}.column.is-offset-two-fifths-touch{margin-right:40%}.column.is-offset-three-fifths-touch{margin-right:60%}.column.is-offset-four-fifths-touch{margin-right:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-right:0}.column.is-1-touch{flex:none;width:8.33333%}.column.is-offset-1-touch{margin-right:8.33333%}.column.is-2-touch{flex:none;width:16.66667%}.column.is-offset-2-touch{margin-right:16.66667%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-right:25%}.column.is-4-touch{flex:none;width:33.33333%}.column.is-offset-4-touch{margin-right:33.33333%}.column.is-5-touch{flex:none;width:41.66667%}.column.is-offset-5-touch{margin-right:41.66667%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-right:50%}.column.is-7-touch{flex:none;width:58.33333%}.column.is-offset-7-touch{margin-right:58.33333%}.column.is-8-touch{flex:none;width:66.66667%}.column.is-offset-8-touch{margin-right:66.66667%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-right:75%}.column.is-10-touch{flex:none;width:83.33333%}.column.is-offset-10-touch{margin-right:83.33333%}.column.is-11-touch{flex:none;width:91.66667%}.column.is-offset-11-touch{margin-right:91.66667%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-right:100%}}@media screen and (min-width:1024px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-right:75%}.column.is-offset-two-thirds-desktop{margin-right:66.6666%}.column.is-offset-half-desktop{margin-right:50%}.column.is-offset-one-third-desktop{margin-right:33.3333%}.column.is-offset-one-quarter-desktop{margin-right:25%}.column.is-offset-one-fifth-desktop{margin-right:20%}.column.is-offset-two-fifths-desktop{margin-right:40%}.column.is-offset-three-fifths-desktop{margin-right:60%}.column.is-offset-four-fifths-desktop{margin-right:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-right:0}.column.is-1-desktop{flex:none;width:8.33333%}.column.is-offset-1-desktop{margin-right:8.33333%}.column.is-2-desktop{flex:none;width:16.66667%}.column.is-offset-2-desktop{margin-right:16.66667%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-right:25%}.column.is-4-desktop{flex:none;width:33.33333%}.column.is-offset-4-desktop{margin-right:33.33333%}.column.is-5-desktop{flex:none;width:41.66667%}.column.is-offset-5-desktop{margin-right:41.66667%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-right:50%}.column.is-7-desktop{flex:none;width:58.33333%}.column.is-offset-7-desktop{margin-right:58.33333%}.column.is-8-desktop{flex:none;width:66.66667%}.column.is-offset-8-desktop{margin-right:66.66667%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-right:75%}.column.is-10-desktop{flex:none;width:83.33333%}.column.is-offset-10-desktop{margin-right:83.33333%}.column.is-11-desktop{flex:none;width:91.66667%}.column.is-offset-11-desktop{margin-right:91.66667%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-right:100%}}@media screen and (min-width:1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-right:75%}.column.is-offset-two-thirds-widescreen{margin-right:66.6666%}.column.is-offset-half-widescreen{margin-right:50%}.column.is-offset-one-third-widescreen{margin-right:33.3333%}.column.is-offset-one-quarter-widescreen{margin-right:25%}.column.is-offset-one-fifth-widescreen{margin-right:20%}.column.is-offset-two-fifths-widescreen{margin-right:40%}.column.is-offset-three-fifths-widescreen{margin-right:60%}.column.is-offset-four-fifths-widescreen{margin-right:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-right:0}.column.is-1-widescreen{flex:none;width:8.33333%}.column.is-offset-1-widescreen{margin-right:8.33333%}.column.is-2-widescreen{flex:none;width:16.66667%}.column.is-offset-2-widescreen{margin-right:16.66667%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-right:25%}.column.is-4-widescreen{flex:none;width:33.33333%}.column.is-offset-4-widescreen{margin-right:33.33333%}.column.is-5-widescreen{flex:none;width:41.66667%}.column.is-offset-5-widescreen{margin-right:41.66667%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-right:50%}.column.is-7-widescreen{flex:none;width:58.33333%}.column.is-offset-7-widescreen{margin-right:58.33333%}.column.is-8-widescreen{flex:none;width:66.66667%}.column.is-offset-8-widescreen{margin-right:66.66667%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-right:75%}.column.is-10-widescreen{flex:none;width:83.33333%}.column.is-offset-10-widescreen{margin-right:83.33333%}.column.is-11-widescreen{flex:none;width:91.66667%}.column.is-offset-11-widescreen{margin-right:91.66667%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-right:100%}}@media screen and (min-width:1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-right:75%}.column.is-offset-two-thirds-fullhd{margin-right:66.6666%}.column.is-offset-half-fullhd{margin-right:50%}.column.is-offset-one-third-fullhd{margin-right:33.3333%}.column.is-offset-one-quarter-fullhd{margin-right:25%}.column.is-offset-one-fifth-fullhd{margin-right:20%}.column.is-offset-two-fifths-fullhd{margin-right:40%}.column.is-offset-three-fifths-fullhd{margin-right:60%}.column.is-offset-four-fifths-fullhd{margin-right:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-right:0}.column.is-1-fullhd{flex:none;width:8.33333%}.column.is-offset-1-fullhd{margin-right:8.33333%}.column.is-2-fullhd{flex:none;width:16.66667%}.column.is-offset-2-fullhd{margin-right:16.66667%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-right:25%}.column.is-4-fullhd{flex:none;width:33.33333%}.column.is-offset-4-fullhd{margin-right:33.33333%}.column.is-5-fullhd{flex:none;width:41.66667%}.column.is-offset-5-fullhd{margin-right:41.66667%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-right:50%}.column.is-7-fullhd{flex:none;width:58.33333%}.column.is-offset-7-fullhd{margin-right:58.33333%}.column.is-8-fullhd{flex:none;width:66.66667%}.column.is-offset-8-fullhd{margin-right:66.66667%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-right:75%}.column.is-10-fullhd{flex:none;width:83.33333%}.column.is-offset-10-fullhd{margin-right:83.33333%}.column.is-11-fullhd{flex:none;width:91.66667%}.column.is-offset-11-fullhd{margin-right:91.66667%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-right:100%}}.columns{margin-right:-.75rem;margin-left:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-right:0;margin-left:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0!important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width:769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width:1024px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap:0.75rem;margin-right:calc(-1 * var(--columnGap));margin-left:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap:0rem}@media screen and (max-width:768px){.columns.is-variable.is-0-mobile{--columnGap:0rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-0-tablet{--columnGap:0rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-0-tablet-only{--columnGap:0rem}}@media screen and (max-width:1023px){.columns.is-variable.is-0-touch{--columnGap:0rem}}@media screen and (min-width:1024px){.columns.is-variable.is-0-desktop{--columnGap:0rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-0-desktop-only{--columnGap:0rem}}@media screen and (min-width:1216px){.columns.is-variable.is-0-widescreen{--columnGap:0rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-0-widescreen-only{--columnGap:0rem}}@media screen and (min-width:1408px){.columns.is-variable.is-0-fullhd{--columnGap:0rem}}.columns.is-variable.is-1{--columnGap:0.25rem}@media screen and (max-width:768px){.columns.is-variable.is-1-mobile{--columnGap:0.25rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-1-tablet{--columnGap:0.25rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-1-tablet-only{--columnGap:0.25rem}}@media screen and (max-width:1023px){.columns.is-variable.is-1-touch{--columnGap:0.25rem}}@media screen and (min-width:1024px){.columns.is-variable.is-1-desktop{--columnGap:0.25rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-1-desktop-only{--columnGap:0.25rem}}@media screen and (min-width:1216px){.columns.is-variable.is-1-widescreen{--columnGap:0.25rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-1-widescreen-only{--columnGap:0.25rem}}@media screen and (min-width:1408px){.columns.is-variable.is-1-fullhd{--columnGap:0.25rem}}.columns.is-variable.is-2{--columnGap:0.5rem}@media screen and (max-width:768px){.columns.is-variable.is-2-mobile{--columnGap:0.5rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-2-tablet{--columnGap:0.5rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-2-tablet-only{--columnGap:0.5rem}}@media screen and (max-width:1023px){.columns.is-variable.is-2-touch{--columnGap:0.5rem}}@media screen and (min-width:1024px){.columns.is-variable.is-2-desktop{--columnGap:0.5rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-2-desktop-only{--columnGap:0.5rem}}@media screen and (min-width:1216px){.columns.is-variable.is-2-widescreen{--columnGap:0.5rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-2-widescreen-only{--columnGap:0.5rem}}@media screen and (min-width:1408px){.columns.is-variable.is-2-fullhd{--columnGap:0.5rem}}.columns.is-variable.is-3{--columnGap:0.75rem}@media screen and (max-width:768px){.columns.is-variable.is-3-mobile{--columnGap:0.75rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-3-tablet{--columnGap:0.75rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-3-tablet-only{--columnGap:0.75rem}}@media screen and (max-width:1023px){.columns.is-variable.is-3-touch{--columnGap:0.75rem}}@media screen and (min-width:1024px){.columns.is-variable.is-3-desktop{--columnGap:0.75rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-3-desktop-only{--columnGap:0.75rem}}@media screen and (min-width:1216px){.columns.is-variable.is-3-widescreen{--columnGap:0.75rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-3-widescreen-only{--columnGap:0.75rem}}@media screen and (min-width:1408px){.columns.is-variable.is-3-fullhd{--columnGap:0.75rem}}.columns.is-variable.is-4{--columnGap:1rem}@media screen and (max-width:768px){.columns.is-variable.is-4-mobile{--columnGap:1rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-4-tablet{--columnGap:1rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-4-tablet-only{--columnGap:1rem}}@media screen and (max-width:1023px){.columns.is-variable.is-4-touch{--columnGap:1rem}}@media screen and (min-width:1024px){.columns.is-variable.is-4-desktop{--columnGap:1rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-4-desktop-only{--columnGap:1rem}}@media screen and (min-width:1216px){.columns.is-variable.is-4-widescreen{--columnGap:1rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-4-widescreen-only{--columnGap:1rem}}@media screen and (min-width:1408px){.columns.is-variable.is-4-fullhd{--columnGap:1rem}}.columns.is-variable.is-5{--columnGap:1.25rem}@media screen and (max-width:768px){.columns.is-variable.is-5-mobile{--columnGap:1.25rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-5-tablet{--columnGap:1.25rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-5-tablet-only{--columnGap:1.25rem}}@media screen and (max-width:1023px){.columns.is-variable.is-5-touch{--columnGap:1.25rem}}@media screen and (min-width:1024px){.columns.is-variable.is-5-desktop{--columnGap:1.25rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-5-desktop-only{--columnGap:1.25rem}}@media screen and (min-width:1216px){.columns.is-variable.is-5-widescreen{--columnGap:1.25rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-5-widescreen-only{--columnGap:1.25rem}}@media screen and (min-width:1408px){.columns.is-variable.is-5-fullhd{--columnGap:1.25rem}}.columns.is-variable.is-6{--columnGap:1.5rem}@media screen and (max-width:768px){.columns.is-variable.is-6-mobile{--columnGap:1.5rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-6-tablet{--columnGap:1.5rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-6-tablet-only{--columnGap:1.5rem}}@media screen and (max-width:1023px){.columns.is-variable.is-6-touch{--columnGap:1.5rem}}@media screen and (min-width:1024px){.columns.is-variable.is-6-desktop{--columnGap:1.5rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-6-desktop-only{--columnGap:1.5rem}}@media screen and (min-width:1216px){.columns.is-variable.is-6-widescreen{--columnGap:1.5rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-6-widescreen-only{--columnGap:1.5rem}}@media screen and (min-width:1408px){.columns.is-variable.is-6-fullhd{--columnGap:1.5rem}}.columns.is-variable.is-7{--columnGap:1.75rem}@media screen and (max-width:768px){.columns.is-variable.is-7-mobile{--columnGap:1.75rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-7-tablet{--columnGap:1.75rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-7-tablet-only{--columnGap:1.75rem}}@media screen and (max-width:1023px){.columns.is-variable.is-7-touch{--columnGap:1.75rem}}@media screen and (min-width:1024px){.columns.is-variable.is-7-desktop{--columnGap:1.75rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-7-desktop-only{--columnGap:1.75rem}}@media screen and (min-width:1216px){.columns.is-variable.is-7-widescreen{--columnGap:1.75rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-7-widescreen-only{--columnGap:1.75rem}}@media screen and (min-width:1408px){.columns.is-variable.is-7-fullhd{--columnGap:1.75rem}}.columns.is-variable.is-8{--columnGap:2rem}@media screen and (max-width:768px){.columns.is-variable.is-8-mobile{--columnGap:2rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-8-tablet{--columnGap:2rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-8-tablet-only{--columnGap:2rem}}@media screen and (max-width:1023px){.columns.is-variable.is-8-touch{--columnGap:2rem}}@media screen and (min-width:1024px){.columns.is-variable.is-8-desktop{--columnGap:2rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-8-desktop-only{--columnGap:2rem}}@media screen and (min-width:1216px){.columns.is-variable.is-8-widescreen{--columnGap:2rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-8-widescreen-only{--columnGap:2rem}}@media screen and (min-width:1408px){.columns.is-variable.is-8-fullhd{--columnGap:2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0!important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem!important}@media screen and (min-width:769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333%}.tile.is-2{flex:none;width:16.66667%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333%}.tile.is-5{flex:none;width:41.66667%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333%}.tile.is-8{flex:none;width:66.66667%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333%}.tile.is-11{flex:none;width:91.66667%}.tile.is-12{flex:none;width:100%}}.has-text-white{color:#fff!important}a.has-text-white:focus,a.has-text-white:hover{color:#e6e6e6!important}.has-background-white{background-color:#fff!important}.has-text-black{color:#0a0a0a!important}a.has-text-black:focus,a.has-text-black:hover{color:#000!important}.has-background-black{background-color:#0a0a0a!important}.has-text-light{color:#f5f5f5!important}a.has-text-light:focus,a.has-text-light:hover{color:#dbdbdb!important}.has-background-light{background-color:#f5f5f5!important}.has-text-dark{color:#363636!important}a.has-text-dark:focus,a.has-text-dark:hover{color:#1c1c1c!important}.has-background-dark{background-color:#363636!important}.has-text-primary{color:#00d1b2!important}a.has-text-primary:focus,a.has-text-primary:hover{color:#009e86!important}.has-background-primary{background-color:#00d1b2!important}.has-text-primary-light{color:#ebfffc!important}a.has-text-primary-light:focus,a.has-text-primary-light:hover{color:#b8fff4!important}.has-background-primary-light{background-color:#ebfffc!important}.has-text-primary-dark{color:#00947e!important}a.has-text-primary-dark:focus,a.has-text-primary-dark:hover{color:#00c7a9!important}.has-background-primary-dark{background-color:#00947e!important}.has-text-link{color:#485fc7!important}a.has-text-link:focus,a.has-text-link:hover{color:#3449a8!important}.has-background-link{background-color:#485fc7!important}.has-text-link-light{color:#eff1fa!important}a.has-text-link-light:focus,a.has-text-link-light:hover{color:#c8cfee!important}.has-background-link-light{background-color:#eff1fa!important}.has-text-link-dark{color:#3850b7!important}a.has-text-link-dark:focus,a.has-text-link-dark:hover{color:#576dcb!important}.has-background-link-dark{background-color:#3850b7!important}.has-text-info{color:#3e8ed0!important}a.has-text-info:focus,a.has-text-info:hover{color:#2b74b1!important}.has-background-info{background-color:#3e8ed0!important}.has-text-info-light{color:#eff5fb!important}a.has-text-info-light:focus,a.has-text-info-light:hover{color:#c6ddf1!important}.has-background-info-light{background-color:#eff5fb!important}.has-text-info-dark{color:#296fa8!important}a.has-text-info-dark:focus,a.has-text-info-dark:hover{color:#368ace!important}.has-background-info-dark{background-color:#296fa8!important}.has-text-success{color:#48c78e!important}a.has-text-success:focus,a.has-text-success:hover{color:#34a873!important}.has-background-success{background-color:#48c78e!important}.has-text-success-light{color:#effaf5!important}a.has-text-success-light:focus,a.has-text-success-light:hover{color:#c8eedd!important}.has-background-success-light{background-color:#effaf5!important}.has-text-success-dark{color:#257953!important}a.has-text-success-dark:focus,a.has-text-success-dark:hover{color:#31a06e!important}.has-background-success-dark{background-color:#257953!important}.has-text-warning{color:#ffe08a!important}a.has-text-warning:focus,a.has-text-warning:hover{color:#ffd257!important}.has-background-warning{background-color:#ffe08a!important}.has-text-warning-light{color:#fffaeb!important}a.has-text-warning-light:focus,a.has-text-warning-light:hover{color:#ffecb8!important}.has-background-warning-light{background-color:#fffaeb!important}.has-text-warning-dark{color:#946c00!important}a.has-text-warning-dark:focus,a.has-text-warning-dark:hover{color:#c79200!important}.has-background-warning-dark{background-color:#946c00!important}.has-text-danger{color:#f14668!important}a.has-text-danger:focus,a.has-text-danger:hover{color:#ee1742!important}.has-background-danger{background-color:#f14668!important}.has-text-danger-light{color:#feecf0!important}a.has-text-danger-light:focus,a.has-text-danger-light:hover{color:#fabdc9!important}.has-background-danger-light{background-color:#feecf0!important}.has-text-danger-dark{color:#cc0f35!important}a.has-text-danger-dark:focus,a.has-text-danger-dark:hover{color:#ee2049!important}.has-background-danger-dark{background-color:#cc0f35!important}.has-text-black-bis{color:#121212!important}.has-background-black-bis{background-color:#121212!important}.has-text-black-ter{color:#242424!important}.has-background-black-ter{background-color:#242424!important}.has-text-grey-darker{color:#363636!important}.has-background-grey-darker{background-color:#363636!important}.has-text-grey-dark{color:#4a4a4a!important}.has-background-grey-dark{background-color:#4a4a4a!important}.has-text-grey{color:#7a7a7a!important}.has-background-grey{background-color:#7a7a7a!important}.has-text-grey-light{color:#b5b5b5!important}.has-background-grey-light{background-color:#b5b5b5!important}.has-text-grey-lighter{color:#dbdbdb!important}.has-background-grey-lighter{background-color:#dbdbdb!important}.has-text-white-ter{color:#f5f5f5!important}.has-background-white-ter{background-color:#f5f5f5!important}.has-text-white-bis{color:#fafafa!important}.has-background-white-bis{background-color:#fafafa!important}.is-flex-direction-row{flex-direction:row!important}.is-flex-direction-row-reverse{flex-direction:row-reverse!important}.is-flex-direction-column{flex-direction:column!important}.is-flex-direction-column-reverse{flex-direction:column-reverse!important}.is-flex-wrap-nowrap{flex-wrap:nowrap!important}.is-flex-wrap-wrap{flex-wrap:wrap!important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse!important}.is-justify-content-flex-start{justify-content:flex-start!important}.is-justify-content-flex-end{justify-content:flex-end!important}.is-justify-content-center{justify-content:center!important}.is-justify-content-space-between{justify-content:space-between!important}.is-justify-content-space-around{justify-content:space-around!important}.is-justify-content-space-evenly{justify-content:space-evenly!important}.is-justify-content-start{justify-content:start!important}.is-justify-content-end{justify-content:end!important}.is-justify-content-left{justify-content:left!important}.is-justify-content-right{justify-content:right!important}.is-align-content-flex-start{align-content:flex-start!important}.is-align-content-flex-end{align-content:flex-end!important}.is-align-content-center{align-content:center!important}.is-align-content-space-between{align-content:space-between!important}.is-align-content-space-around{align-content:space-around!important}.is-align-content-space-evenly{align-content:space-evenly!important}.is-align-content-stretch{align-content:stretch!important}.is-align-content-start{align-content:start!important}.is-align-content-end{align-content:end!important}.is-align-content-baseline{align-content:baseline!important}.is-align-items-stretch{align-items:stretch!important}.is-align-items-flex-start{align-items:flex-start!important}.is-align-items-flex-end{align-items:flex-end!important}.is-align-items-center{align-items:center!important}.is-align-items-baseline{align-items:baseline!important}.is-align-items-start{align-items:start!important}.is-align-items-end{align-items:end!important}.is-align-items-self-start{align-items:self-start!important}.is-align-items-self-end{align-items:self-end!important}.is-align-self-auto{align-self:auto!important}.is-align-self-flex-start{align-self:flex-start!important}.is-align-self-flex-end{align-self:flex-end!important}.is-align-self-center{align-self:center!important}.is-align-self-baseline{align-self:baseline!important}.is-align-self-stretch{align-self:stretch!important}.is-flex-grow-0{flex-grow:0!important}.is-flex-grow-1{flex-grow:1!important}.is-flex-grow-2{flex-grow:2!important}.is-flex-grow-3{flex-grow:3!important}.is-flex-grow-4{flex-grow:4!important}.is-flex-grow-5{flex-grow:5!important}.is-flex-shrink-0{flex-shrink:0!important}.is-flex-shrink-1{flex-shrink:1!important}.is-flex-shrink-2{flex-shrink:2!important}.is-flex-shrink-3{flex-shrink:3!important}.is-flex-shrink-4{flex-shrink:4!important}.is-flex-shrink-5{flex-shrink:5!important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left!important}.is-pulled-right{float:right!important}.is-radiusless{border-radius:0!important}.is-shadowless{box-shadow:none!important}.is-clickable{cursor:pointer!important;pointer-events:all!important}.is-clipped{overflow:hidden!important}.is-relative{position:relative!important}.is-marginless{margin:0!important}.is-paddingless{padding:0!important}.m-0{margin:0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-left:0!important;margin-right:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:.25rem!important}.mt-1{margin-top:.25rem!important}.mr-1{margin-right:.25rem!important}.mb-1{margin-bottom:.25rem!important}.ml-1{margin-left:.25rem!important}.mx-1{margin-left:.25rem!important;margin-right:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-2{margin:.5rem!important}.mt-2{margin-top:.5rem!important}.mr-2{margin-right:.5rem!important}.mb-2{margin-bottom:.5rem!important}.ml-2{margin-left:.5rem!important}.mx-2{margin-left:.5rem!important;margin-right:.5rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-3{margin:.75rem!important}.mt-3{margin-top:.75rem!important}.mr-3{margin-right:.75rem!important}.mb-3{margin-bottom:.75rem!important}.ml-3{margin-left:.75rem!important}.mx-3{margin-left:.75rem!important;margin-right:.75rem!important}.my-3{margin-top:.75rem!important;margin-bottom:.75rem!important}.m-4{margin:1rem!important}.mt-4{margin-top:1rem!important}.mr-4{margin-right:1rem!important}.mb-4{margin-bottom:1rem!important}.ml-4{margin-left:1rem!important}.mx-4{margin-left:1rem!important;margin-right:1rem!important}.my-4{margin-top:1rem!important;margin-bottom:1rem!important}.m-5{margin:1.5rem!important}.mt-5{margin-top:1.5rem!important}.mr-5{margin-right:1.5rem!important}.mb-5{margin-bottom:1.5rem!important}.ml-5{margin-left:1.5rem!important}.mx-5{margin-left:1.5rem!important;margin-right:1.5rem!important}.my-5{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-6{margin:3rem!important}.mt-6{margin-top:3rem!important}.mr-6{margin-right:3rem!important}.mb-6{margin-bottom:3rem!important}.ml-6{margin-left:3rem!important}.mx-6{margin-left:3rem!important;margin-right:3rem!important}.my-6{margin-top:3rem!important;margin-bottom:3rem!important}.m-auto{margin:auto!important}.mt-auto{margin-top:auto!important}.mr-auto{margin-right:auto!important}.mb-auto{margin-bottom:auto!important}.ml-auto{margin-left:auto!important}.mx-auto{margin-left:auto!important;margin-right:auto!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.p-0{padding:0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-left:0!important;padding-right:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:.25rem!important}.pt-1{padding-top:.25rem!important}.pr-1{padding-right:.25rem!important}.pb-1{padding-bottom:.25rem!important}.pl-1{padding-left:.25rem!important}.px-1{padding-left:.25rem!important;padding-right:.25rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-2{padding:.5rem!important}.pt-2{padding-top:.5rem!important}.pr-2{padding-right:.5rem!important}.pb-2{padding-bottom:.5rem!important}.pl-2{padding-left:.5rem!important}.px-2{padding-left:.5rem!important;padding-right:.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-3{padding:.75rem!important}.pt-3{padding-top:.75rem!important}.pr-3{padding-right:.75rem!important}.pb-3{padding-bottom:.75rem!important}.pl-3{padding-left:.75rem!important}.px-3{padding-left:.75rem!important;padding-right:.75rem!important}.py-3{padding-top:.75rem!important;padding-bottom:.75rem!important}.p-4{padding:1rem!important}.pt-4{padding-top:1rem!important}.pr-4{padding-right:1rem!important}.pb-4{padding-bottom:1rem!important}.pl-4{padding-left:1rem!important}.px-4{padding-left:1rem!important;padding-right:1rem!important}.py-4{padding-top:1rem!important;padding-bottom:1rem!important}.p-5{padding:1.5rem!important}.pt-5{padding-top:1.5rem!important}.pr-5{padding-right:1.5rem!important}.pb-5{padding-bottom:1.5rem!important}.pl-5{padding-left:1.5rem!important}.px-5{padding-left:1.5rem!important;padding-right:1.5rem!important}.py-5{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-6{padding:3rem!important}.pt-6{padding-top:3rem!important}.pr-6{padding-right:3rem!important}.pb-6{padding-bottom:3rem!important}.pl-6{padding-left:3rem!important}.px-6{padding-left:3rem!important;padding-right:3rem!important}.py-6{padding-top:3rem!important;padding-bottom:3rem!important}.p-auto{padding:auto!important}.pt-auto{padding-top:auto!important}.pr-auto{padding-right:auto!important}.pb-auto{padding-bottom:auto!important}.pl-auto{padding-left:auto!important}.px-auto{padding-left:auto!important;padding-right:auto!important}.py-auto{padding-top:auto!important;padding-bottom:auto!important}.is-size-1{font-size:3rem!important}.is-size-2{font-size:2.5rem!important}.is-size-3{font-size:2rem!important}.is-size-4{font-size:1.5rem!important}.is-size-5{font-size:1.25rem!important}.is-size-6{font-size:1rem!important}.is-size-7{font-size:.75rem!important}@media screen and (max-width:768px){.is-size-1-mobile{font-size:3rem!important}.is-size-2-mobile{font-size:2.5rem!important}.is-size-3-mobile{font-size:2rem!important}.is-size-4-mobile{font-size:1.5rem!important}.is-size-5-mobile{font-size:1.25rem!important}.is-size-6-mobile{font-size:1rem!important}.is-size-7-mobile{font-size:.75rem!important}}@media screen and (min-width:769px),print{.is-size-1-tablet{font-size:3rem!important}.is-size-2-tablet{font-size:2.5rem!important}.is-size-3-tablet{font-size:2rem!important}.is-size-4-tablet{font-size:1.5rem!important}.is-size-5-tablet{font-size:1.25rem!important}.is-size-6-tablet{font-size:1rem!important}.is-size-7-tablet{font-size:.75rem!important}}@media screen and (max-width:1023px){.is-size-1-touch{font-size:3rem!important}.is-size-2-touch{font-size:2.5rem!important}.is-size-3-touch{font-size:2rem!important}.is-size-4-touch{font-size:1.5rem!important}.is-size-5-touch{font-size:1.25rem!important}.is-size-6-touch{font-size:1rem!important}.is-size-7-touch{font-size:.75rem!important}}@media screen and (min-width:1024px){.is-size-1-desktop{font-size:3rem!important}.is-size-2-desktop{font-size:2.5rem!important}.is-size-3-desktop{font-size:2rem!important}.is-size-4-desktop{font-size:1.5rem!important}.is-size-5-desktop{font-size:1.25rem!important}.is-size-6-desktop{font-size:1rem!important}.is-size-7-desktop{font-size:.75rem!important}}@media screen and (min-width:1216px){.is-size-1-widescreen{font-size:3rem!important}.is-size-2-widescreen{font-size:2.5rem!important}.is-size-3-widescreen{font-size:2rem!important}.is-size-4-widescreen{font-size:1.5rem!important}.is-size-5-widescreen{font-size:1.25rem!important}.is-size-6-widescreen{font-size:1rem!important}.is-size-7-widescreen{font-size:.75rem!important}}@media screen and (min-width:1408px){.is-size-1-fullhd{font-size:3rem!important}.is-size-2-fullhd{font-size:2.5rem!important}.is-size-3-fullhd{font-size:2rem!important}.is-size-4-fullhd{font-size:1.5rem!important}.is-size-5-fullhd{font-size:1.25rem!important}.is-size-6-fullhd{font-size:1rem!important}.is-size-7-fullhd{font-size:.75rem!important}}.has-text-centered{text-align:center!important}.has-text-justified{text-align:justify!important}.has-text-left{text-align:left!important}.has-text-right{text-align:right!important}@media screen and (max-width:768px){.has-text-centered-mobile{text-align:center!important}}@media screen and (min-width:769px),print{.has-text-centered-tablet{text-align:center!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-centered-tablet-only{text-align:center!important}}@media screen and (max-width:1023px){.has-text-centered-touch{text-align:center!important}}@media screen and (min-width:1024px){.has-text-centered-desktop{text-align:center!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-centered-desktop-only{text-align:center!important}}@media screen and (min-width:1216px){.has-text-centered-widescreen{text-align:center!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-centered-widescreen-only{text-align:center!important}}@media screen and (min-width:1408px){.has-text-centered-fullhd{text-align:center!important}}@media screen and (max-width:768px){.has-text-justified-mobile{text-align:justify!important}}@media screen and (min-width:769px),print{.has-text-justified-tablet{text-align:justify!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-justified-tablet-only{text-align:justify!important}}@media screen and (max-width:1023px){.has-text-justified-touch{text-align:justify!important}}@media screen and (min-width:1024px){.has-text-justified-desktop{text-align:justify!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-justified-desktop-only{text-align:justify!important}}@media screen and (min-width:1216px){.has-text-justified-widescreen{text-align:justify!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-justified-widescreen-only{text-align:justify!important}}@media screen and (min-width:1408px){.has-text-justified-fullhd{text-align:justify!important}}@media screen and (max-width:768px){.has-text-left-mobile{text-align:left!important}}@media screen and (min-width:769px),print{.has-text-left-tablet{text-align:left!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-left-tablet-only{text-align:left!important}}@media screen and (max-width:1023px){.has-text-left-touch{text-align:left!important}}@media screen and (min-width:1024px){.has-text-left-desktop{text-align:left!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-left-desktop-only{text-align:left!important}}@media screen and (min-width:1216px){.has-text-left-widescreen{text-align:left!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-left-widescreen-only{text-align:left!important}}@media screen and (min-width:1408px){.has-text-left-fullhd{text-align:left!important}}@media screen and (max-width:768px){.has-text-right-mobile{text-align:right!important}}@media screen and (min-width:769px),print{.has-text-right-tablet{text-align:right!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-right-tablet-only{text-align:right!important}}@media screen and (max-width:1023px){.has-text-right-touch{text-align:right!important}}@media screen and (min-width:1024px){.has-text-right-desktop{text-align:right!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-right-desktop-only{text-align:right!important}}@media screen and (min-width:1216px){.has-text-right-widescreen{text-align:right!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-right-widescreen-only{text-align:right!important}}@media screen and (min-width:1408px){.has-text-right-fullhd{text-align:right!important}}.is-capitalized{text-transform:capitalize!important}.is-lowercase{text-transform:lowercase!important}.is-uppercase{text-transform:uppercase!important}.is-italic{font-style:italic!important}.is-underlined{text-decoration:underline!important}.has-text-weight-light{font-weight:300!important}.has-text-weight-normal{font-weight:400!important}.has-text-weight-medium{font-weight:500!important}.has-text-weight-semibold{font-weight:600!important}.has-text-weight-bold{font-weight:700!important}.is-family-primary{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-secondary{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-sans-serif{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-monospace{font-family:monospace!important}.is-family-code{font-family:monospace!important}.is-block{display:block!important}@media screen and (max-width:768px){.is-block-mobile{display:block!important}}@media screen and (min-width:769px),print{.is-block-tablet{display:block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-block-tablet-only{display:block!important}}@media screen and (max-width:1023px){.is-block-touch{display:block!important}}@media screen and (min-width:1024px){.is-block-desktop{display:block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-block-desktop-only{display:block!important}}@media screen and (min-width:1216px){.is-block-widescreen{display:block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-block-widescreen-only{display:block!important}}@media screen and (min-width:1408px){.is-block-fullhd{display:block!important}}.is-flex{display:flex!important}@media screen and (max-width:768px){.is-flex-mobile{display:flex!important}}@media screen and (min-width:769px),print{.is-flex-tablet{display:flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-flex-tablet-only{display:flex!important}}@media screen and (max-width:1023px){.is-flex-touch{display:flex!important}}@media screen and (min-width:1024px){.is-flex-desktop{display:flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-flex-desktop-only{display:flex!important}}@media screen and (min-width:1216px){.is-flex-widescreen{display:flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-flex-widescreen-only{display:flex!important}}@media screen and (min-width:1408px){.is-flex-fullhd{display:flex!important}}.is-inline{display:inline!important}@media screen and (max-width:768px){.is-inline-mobile{display:inline!important}}@media screen and (min-width:769px),print{.is-inline-tablet{display:inline!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-tablet-only{display:inline!important}}@media screen and (max-width:1023px){.is-inline-touch{display:inline!important}}@media screen and (min-width:1024px){.is-inline-desktop{display:inline!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-desktop-only{display:inline!important}}@media screen and (min-width:1216px){.is-inline-widescreen{display:inline!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-widescreen-only{display:inline!important}}@media screen and (min-width:1408px){.is-inline-fullhd{display:inline!important}}.is-inline-block{display:inline-block!important}@media screen and (max-width:768px){.is-inline-block-mobile{display:inline-block!important}}@media screen and (min-width:769px),print{.is-inline-block-tablet{display:inline-block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-block-tablet-only{display:inline-block!important}}@media screen and (max-width:1023px){.is-inline-block-touch{display:inline-block!important}}@media screen and (min-width:1024px){.is-inline-block-desktop{display:inline-block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-block-desktop-only{display:inline-block!important}}@media screen and (min-width:1216px){.is-inline-block-widescreen{display:inline-block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-block-widescreen-only{display:inline-block!important}}@media screen and (min-width:1408px){.is-inline-block-fullhd{display:inline-block!important}}.is-inline-flex{display:inline-flex!important}@media screen and (max-width:768px){.is-inline-flex-mobile{display:inline-flex!important}}@media screen and (min-width:769px),print{.is-inline-flex-tablet{display:inline-flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-flex-tablet-only{display:inline-flex!important}}@media screen and (max-width:1023px){.is-inline-flex-touch{display:inline-flex!important}}@media screen and (min-width:1024px){.is-inline-flex-desktop{display:inline-flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-flex-desktop-only{display:inline-flex!important}}@media screen and (min-width:1216px){.is-inline-flex-widescreen{display:inline-flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-flex-widescreen-only{display:inline-flex!important}}@media screen and (min-width:1408px){.is-inline-flex-fullhd{display:inline-flex!important}}.is-hidden{display:none!important}.is-sr-only{border:none!important;clip:rect(0,0,0,0)!important;height:.01em!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:.01em!important}@media screen and (max-width:768px){.is-hidden-mobile{display:none!important}}@media screen and (min-width:769px),print{.is-hidden-tablet{display:none!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-hidden-tablet-only{display:none!important}}@media screen and (max-width:1023px){.is-hidden-touch{display:none!important}}@media screen and (min-width:1024px){.is-hidden-desktop{display:none!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-hidden-desktop-only{display:none!important}}@media screen and (min-width:1216px){.is-hidden-widescreen{display:none!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-hidden-widescreen-only{display:none!important}}@media screen and (min-width:1408px){.is-hidden-fullhd{display:none!important}}.is-invisible{visibility:hidden!important}@media screen and (max-width:768px){.is-invisible-mobile{visibility:hidden!important}}@media screen and (min-width:769px),print{.is-invisible-tablet{visibility:hidden!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-invisible-tablet-only{visibility:hidden!important}}@media screen and (max-width:1023px){.is-invisible-touch{visibility:hidden!important}}@media screen and (min-width:1024px){.is-invisible-desktop{visibility:hidden!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-invisible-desktop-only{visibility:hidden!important}}@media screen and (min-width:1216px){.is-invisible-widescreen{visibility:hidden!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-invisible-widescreen-only{visibility:hidden!important}}@media screen and (min-width:1408px){.is-invisible-fullhd{visibility:hidden!important}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:0 0}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width:1023px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,.7)}.hero.is-white .navbar-link.is-active,.hero.is-white .navbar-link:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff!important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,.7)}.hero.is-black .navbar-link.is-active,.hero.is-black .navbar-link:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black a.navbar-item:hover{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a!important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}@media screen and (max-width:768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,.7)}.hero.is-light .subtitle{color:rgba(0,0,0,.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,.7)}@media screen and (max-width:1023px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,.7)}.hero.is-light .navbar-link.is-active,.hero.is-light .navbar-link:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.hero.is-light .tabs a{color:rgba(0,0,0,.7);opacity:.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5!important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,.7);border-color:rgba(0,0,0,.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}}.hero.is-dark{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong{color:inherit}.hero.is-dark .title{color:#fff}.hero.is-dark .subtitle{color:rgba(255,255,255,.9)}.hero.is-dark .subtitle a:not(.button),.hero.is-dark .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-dark .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.hero.is-dark .navbar-link{color:rgba(255,255,255,.7)}.hero.is-dark .navbar-link.is-active,.hero.is-dark .navbar-link:hover,.hero.is-dark a.navbar-item.is-active,.hero.is-dark a.navbar-item:hover{background-color:#292929;color:#fff}.hero.is-dark .tabs a{color:#fff;opacity:.9}.hero.is-dark .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a{color:#363636!important;opacity:1}.hero.is-dark .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}@media screen and (max-width:768px){.hero.is-dark.is-bold .navbar-menu{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}}.hero.is-primary{background-color:#00d1b2;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong{color:inherit}.hero.is-primary .title{color:#fff}.hero.is-primary .subtitle{color:rgba(255,255,255,.9)}.hero.is-primary .subtitle a:not(.button),.hero.is-primary .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-primary .navbar-menu{background-color:#00d1b2}}.hero.is-primary .navbar-item,.hero.is-primary .navbar-link{color:rgba(255,255,255,.7)}.hero.is-primary .navbar-link.is-active,.hero.is-primary .navbar-link:hover,.hero.is-primary a.navbar-item.is-active,.hero.is-primary a.navbar-item:hover{background-color:#00b89c;color:#fff}.hero.is-primary .tabs a{color:#fff;opacity:.9}.hero.is-primary .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a{color:#00d1b2!important;opacity:1}.hero.is-primary .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#00d1b2}.hero.is-primary.is-bold{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}@media screen and (max-width:768px){.hero.is-primary.is-bold .navbar-menu{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}}.hero.is-link{background-color:#485fc7;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-link .navbar-menu{background-color:#485fc7}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,.7)}.hero.is-link .navbar-link.is-active,.hero.is-link .navbar-link:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link a.navbar-item:hover{background-color:#3a51bb;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#485fc7!important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#485fc7}.hero.is-link.is-bold{background-image:linear-gradient(141deg,#2959b3 0,#485fc7 71%,#5658d2 100%)}@media screen and (max-width:768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg,#2959b3 0,#485fc7 71%,#5658d2 100%)}}.hero.is-info{background-color:#3e8ed0;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-info .navbar-menu{background-color:#3e8ed0}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,.7)}.hero.is-info .navbar-link.is-active,.hero.is-info .navbar-link:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info a.navbar-item:hover{background-color:#3082c5;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#3e8ed0!important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#3e8ed0}.hero.is-info.is-bold{background-image:linear-gradient(141deg,#208fbc 0,#3e8ed0 71%,#4d83db 100%)}@media screen and (max-width:768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg,#208fbc 0,#3e8ed0 71%,#4d83db 100%)}}.hero.is-success{background-color:#48c78e;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-success .navbar-menu{background-color:#48c78e}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,.7)}.hero.is-success .navbar-link.is-active,.hero.is-success .navbar-link:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success a.navbar-item:hover{background-color:#3abb81;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#48c78e!important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#48c78e}.hero.is-success.is-bold{background-image:linear-gradient(141deg,#29b35e 0,#48c78e 71%,#56d2af 100%)}@media screen and (max-width:768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg,#29b35e 0,#48c78e 71%,#56d2af 100%)}}.hero.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,.7)}@media screen and (max-width:1023px){.hero.is-warning .navbar-menu{background-color:#ffe08a}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,.7)}.hero.is-warning .navbar-link.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,.7);opacity:.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffe08a!important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,.7);border-color:rgba(0,0,0,.7);color:#ffe08a}.hero.is-warning.is-bold{background-image:linear-gradient(141deg,#ffb657 0,#ffe08a 71%,#fff6a3 100%)}@media screen and (max-width:768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg,#ffb657 0,#ffe08a 71%,#fff6a3 100%)}}.hero.is-danger{background-color:#f14668;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-danger .navbar-menu{background-color:#f14668}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,.7)}.hero.is-danger .navbar-link.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger a.navbar-item:hover{background-color:#ef2e55;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#f14668!important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#f14668}.hero.is-danger.is-bold{background-image:linear-gradient(141deg,#fa0a62 0,#f14668 71%,#f7595f 100%)}@media screen and (max-width:768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg,#fa0a62 0,#f14668 71%,#f7595f 100%)}}.hero.is-small .hero-body{padding:1.5rem}@media screen and (min-width:769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width:769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body,.hero.is-halfheight .hero-body{align-items:center;display:flex}.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container,.hero.is-halfheight .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.hero-video.is-transparent{opacity:.3}@media screen and (max-width:768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width:768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:.75rem}}@media screen and (min-width:769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-left:1.5rem}}.hero-foot,.hero-head{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width:769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width:1024px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem} \ No newline at end of file diff --git a/pagetop/static/bulmix/css/bulma-rtl.min.css.map b/pagetop/static/bulmix/css/bulma-rtl.min.css.map new file mode 100644 index 00000000..731168fb --- /dev/null +++ b/pagetop/static/bulmix/css/bulma-rtl.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../bulma.sass","../sass/utilities/_all.sass","../sass/utilities/extends.sass","../sass/utilities/controls.sass","../sass/utilities/initial-variables.sass","bulma-rtl.css","../sass/utilities/mixins.sass","../sass/base/_all.sass","../sass/base/minireset.sass","../sass/base/generic.sass","../sass/utilities/derived-variables.sass","../sass/base/animations.sass","../sass/elements/_all.sass","../sass/elements/box.sass","../sass/elements/button.sass","../sass/utilities/functions.sass","../sass/elements/container.sass","../sass/elements/content.sass","../sass/elements/icon.sass","../sass/elements/image.sass","../sass/elements/notification.sass","../sass/elements/progress.sass","../sass/elements/table.sass","../sass/elements/tag.sass","../sass/elements/title.sass","../sass/elements/other.sass","../sass/form/_all.sass","../sass/form/shared.sass","../sass/form/input-textarea.sass","../sass/form/checkbox-radio.sass","../sass/form/select.sass","../sass/form/file.sass","../sass/form/tools.sass","../sass/components/_all.sass","../sass/components/breadcrumb.sass","../sass/components/card.sass","../sass/components/dropdown.sass","../sass/components/level.sass","../sass/components/media.sass","../sass/components/menu.sass","../sass/components/message.sass","../sass/components/modal.sass","../sass/components/navbar.sass","../sass/components/pagination.sass","../sass/components/panel.sass","../sass/components/tabs.sass","../sass/grid/_all.sass","../sass/grid/columns.sass","../sass/grid/tiles.sass","../sass/helpers/_all.sass","../sass/helpers/color.sass","../sass/helpers/flexbox.sass","../sass/helpers/float.sass","../sass/helpers/other.sass","../sass/helpers/overflow.sass","../sass/helpers/position.sass","../sass/helpers/spacing.sass","../sass/helpers/typography.sass","../sass/helpers/visibility.sass","../sass/layout/_all.sass","../sass/layout/hero.sass","../sass/layout/section.sass","../sass/layout/footer.sass"],"names":[],"mappings":"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,4BAA4B;EAC5B,sBLpC0B;ACkU5B;;AI5RA;EACE,cL7D4B;EK8D5B,cA1DkB;EA2DlB,gBL7BiB;EK8BjB,gBA1DoB;AJyVtB;;AI3RA;EACE,cLtDgC;EKuDhC,eAAe;EACf,qBAAqB;AJ8RvB;;AIjSA;EAKI,mBAAmB;AJgSvB;;AIrSA;EAOI,cL5E0B;AC8W9B;;AIhSA;EACE,4BLxE4B;EKyE5B,cCnBsB;EDoBtB,kBArEiB;EAsEjB,mBAvEkB;EAwElB,4BAzEgC;AJ4WlC;;AIjSA;EACE,4BL/E4B;EKgF5B,YAAY;EACZ,cAAc;EACd,WAxEa;EAyEb,gBAxEkB;AJ4WpB;;AIlSA;EACE,YAAY;EACZ,eAAe;AJqSjB;;AInSA;;EAEE,wBAAwB;AJsS1B;;AIpSA;EACE,kBAvFuB;AJ8XzB;;AIrSA;EACE,mBAAmB;EACnB,oBAAoB;AJwStB;;AItSA;EACE,cL5G4B;EK6G5B,gBLvEe;ACgXjB;;AIrSA;EACE,YAAY;AJwSd;;AItSA;EH5DE,iCAAiC;EG8DjC,4BL/G4B;EKgH5B,cLtH4B;EKuH5B,kBAjGqB;EAkGrB,gBAAgB;EAChB,uBAlG0B;EAmG1B,gBAAgB;EAChB,iBAAiB;AJySnB;;AIjTA;EAUI,6BAA6B;EAC7B,mBAAmB;EACnB,cAvGoB;EAwGpB,UAAU;AJ2Sd;;AIzSA;;EAGI,mBAAmB;AJ2SvB;;AI9SA;;EAKM,mBAAmB;AJ8SzB;;AInTA;EAOI,cL1I0B;AC0b9B;;AMhcA;EACE;IACE,uBAAuB;ENmczB;EMlcA;IACE,yBAAyB;ENoc3B;AACF;;AMzcA;EACE;IACE,uBAAuB;ENmczB;EMlcA;IACE,yBAAyB;ENoc3B;AACF;;AOzcA,mBAAA;ACWA;EAEE,uBTE6B;ESD7B,kBTwDgB;ESvDhB,0FTb2B;ESc3B,cTT4B;ESU5B,cAAc;EACd,gBAZmB;AR6crB;;AQ/bA;EAGI,yETD8B;ACiclC;;AQncA;EAKI,oETH8B;ACqclC;;AShaA;EAGE,uBV/C6B;EUgD7B,qBVrD4B;EUsD5B,iBX3DwB;EW4DxB,cV3D4B;EU4D5B,eAAe;EAGf,uBAAuB;EACvB,iCA5D6D;EA6D7D,iBA5D6B;EA6D7B,kBA7D6B;EA8D7B,8BA/D6D;EAgE7D,kBAAkB;EAClB,mBAAmB;AT+ZrB;;AS/aA;EAkBI,cAAc;ATialB;;ASnbA;EAwBM,aAAa;EACb,YAAY;AT+ZlB;;ASxbA;ER+FI,gCQpEsG;ERoEtG,mBQnEmE;ATiavE;;AS7bA;ER+FI,oBQjEmE;ERiEnE,+BQhEsG;ATma1G;;ASlcA;EAiCM,+BAAiF;EACjF,gCAAkF;ATqaxF;;ASvcA;EAsCI,qBVxF0B;EUyF1B,cV5F0B;ACigB9B;;AS5cA;EA0CI,qBV/E8B;EUgF9B,cVhG0B;ACsgB9B;;ASjdA;EA6CM,iDVlF4B;AC0flC;;ASrdA;EAgDI,qBVpG0B;EUqG1B,cVtG0B;AC+gB9B;;AS1dA;EAoDI,6BAA6B;EAC7B,yBAAyB;EACzB,cV1G0B;EU2G1B,0BAzF8B;ATmgBlC;;ASjeA;EA4DM,4BV1GwB;EU2GxB,cVlHwB;AC2hB9B;;ASteA;EAgEM,yBCd2B;EDe3B,cVtHwB;ACgiB9B;;AS3eA;;EAoEM,6BAA6B;EAC7B,yBAAyB;EACzB,gBAAgB;AT4atB;;ASlfA;EAwEI,gBAtG0B;EAuG1B,yBAtGmC;EAuGnC,cV/G8B;EUgH9B,qBAtG0B;ATohB9B;;ASzfA;EA8EM,cVnH4B;EUoH5B,0BAxGmC;ATuhBzC;;AS9fA;EAoFM,uBVhIyB;EUiIzB,yBAAyB;EACzB,cV/IuB;AC6jB7B;;ASpgBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,cVpJqB;ACmkB7B;;AS1gBA;EA8FQ,yBAAyB;EACzB,cVxJqB;ACwkB7B;;AS/gBA;EAiGU,mDV7IqB;AC+jB/B;;ASnhBA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,cV/JqB;ACklB7B;;ASzhBA;;EAyGQ,uBVrJuB;EUsJvB,yBAAyB;EACzB,gBAAgB;ATqbxB;;AShiBA;EA6GQ,yBVtKqB;EUuKrB,YV1JuB;ACilB/B;;ASriBA;EAiHU,uBC/DuB;AVufjC;;ASziBA;;EAoHU,yBV7KmB;EU8KnB,yBAAyB;EACzB,gBAAgB;EAChB,YVnKqB;AC6lB/B;;ASjjBA;EA0HU,gEAA4E;AT2btF;;ASrjBA;EA4HQ,6BAA6B;EAC7B,mBVzKuB;EU0KvB,YV1KuB;ACumB/B;;AS3jBA;EAmIU,uBV/KqB;EUgLrB,mBVhLqB;EUiLrB,cV9LmB;AC0nB7B;;ASjkBA;EAwIY,4DAA8D;AT6b1E;;ASrkBA;EA8Ic,gEAA4E;AT2b1F;;ASzkBA;;EAiJU,6BAA6B;EAC7B,mBV9LqB;EU+LrB,gBAAgB;EAChB,YVhMqB;AC6nB/B;;ASjlBA;EAsJQ,6BAA6B;EAC7B,qBVhNqB;EUiNrB,cVjNqB;ACgpB7B;;ASvlBA;EA6JU,yBVtNmB;EUuNnB,YV1MqB;ACwoB/B;;AS5lBA;EAqKc,4DAA8D;AT2b5E;;AShmBA;;EAwKU,6BAA6B;EAC7B,qBVlOmB;EUmOnB,gBAAgB;EAChB,cVpOmB;ACiqB7B;;ASxmBA;EAoFM,yBV7IuB;EU8IvB,yBAAyB;EACzB,YVlIyB;AC0pB/B;;AS9mBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,YVvIuB;ACgqB/B;;ASpnBA;EA8FQ,yBAAyB;EACzB,YV3IuB;ACqqB/B;;ASznBA;EAiGU,gDV1JmB;ACsrB7B;;AS7nBA;EAoGQ,uBClDyB;EDmDzB,yBAAyB;EACzB,YVlJuB;AC+qB/B;;ASnoBA;;EAyGQ,yBVlKqB;EUmKrB,yBAAyB;EACzB,gBAAgB;AT+hBxB;;AS1oBA;EA6GQ,uBVzJuB;EU0JvB,cVvKqB;ACwsB7B;;AS/oBA;EAiHU,yBC/DuB;AVimBjC;;ASnpBA;;EAoHU,uBVhKqB;EUiKrB,yBAAyB;EACzB,gBAAgB;EAChB,cVhLmB;ACotB7B;;AS3pBA;EA0HU,4DAA4E;ATqiBtF;;AS/pBA;EA4HQ,6BAA6B;EAC7B,qBVtLqB;EUuLrB,cVvLqB;AC8tB7B;;ASrqBA;EAmIU,yBV5LmB;EU6LnB,qBV7LmB;EU8LnB,YVjLqB;ACutB/B;;AS3qBA;EAwIY,gEAA8D;ATuiB1E;;AS/qBA;EA8Ic,4DAA4E;ATqiB1F;;ASnrBA;;EAiJU,6BAA6B;EAC7B,qBV3MmB;EU4MnB,gBAAgB;EAChB,cV7MmB;ACovB7B;;AS3rBA;EAsJQ,6BAA6B;EAC7B,mBVnMuB;EUoMvB,YVpMuB;AC6uB/B;;ASjsBA;EA6JU,uBVzMqB;EU0MrB,cVvNmB;AC+vB7B;;AStsBA;EAqKc,gEAA8D;ATqiB5E;;AS1sBA;;EAwKU,6BAA6B;EAC7B,mBVrNqB;EUsNrB,gBAAgB;EAChB,YVvNqB;AC8vB/B;;ASltBA;EAoFM,4BVlIwB;EUmIxB,yBAAyB;EACzB,yBCjEe;AVmsBrB;;ASxtBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,yBCtEa;AVysBrB;;AS9tBA;EA8FQ,yBAAyB;EACzB,yBC1Ea;AV8sBrB;;ASnuBA;EAiGU,mDV/IoB;ACqxB9B;;ASvuBA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,yBCjFa;AVwtBrB;;AS7uBA;;EAyGQ,4BVvJsB;EUwJtB,yBAAyB;EACzB,gBAAgB;ATyoBxB;;ASpvBA;EA6GQ,oCCxFa;EDyFb,iBV5JsB;ACuyB9B;;ASzvBA;EAiHU,oCC/DuB;AV2sBjC;;AS7vBA;;EAoHU,oCC/FW;EDgGX,yBAAyB;EACzB,gBAAgB;EAChB,iBVrKoB;ACmzB9B;;ASrwBA;EA0HU,sFAA4E;AT+oBtF;;ASzwBA;EA4HQ,6BAA6B;EAC7B,wBV3KsB;EU4KtB,iBV5KsB;AC6zB9B;;AS/wBA;EAmIU,4BVjLoB;EUkLpB,wBVlLoB;EUmLpB,yBChHW;AVgwBrB;;ASrxBA;EAwIY,sEAA8D;ATipB1E;;ASzxBA;EA8Ic,sFAA4E;AT+oB1F;;AS7xBA;;EAiJU,6BAA6B;EAC7B,wBVhMoB;EUiMpB,gBAAgB;EAChB,iBVlMoB;ACm1B9B;;ASryBA;EAsJQ,6BAA6B;EAC7B,gCClIa;EDmIb,yBCnIa;AVsxBrB;;AS3yBA;EA6JU,oCCxIW;EDyIX,iBV5MoB;AC81B9B;;AShzBA;EAqKc,sEAA8D;AT+oB5E;;ASpzBA;;EAwKU,6BAA6B;EAC7B,gCCpJW;EDqJX,gBAAgB;EAChB,yBCtJW;AVuyBrB;;AS5zBA;EAoFM,yBVzIwB;EU0IxB,yBAAyB;EACzB,WC/DU;AV2yBhB;;ASl0BA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVizBhB;;ASx0BA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVszBhB;;AS70BA;EAiGU,gDVtJoB;ACs4B9B;;ASj1BA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVg0BhB;;ASv1BA;;EAyGQ,yBV9JsB;EU+JtB,yBAAyB;EACzB,gBAAgB;ATmvBxB;;AS91BA;EA6GQ,sBCtFQ;EDuFR,cVnKsB;ACw5B9B;;ASn2BA;EAiHU,yBC/DuB;AVqzBjC;;ASv2BA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV5KoB;ACo6B9B;;AS/2BA;EA0HU,0DAA4E;ATyvBtF;;ASn3BA;EA4HQ,6BAA6B;EAC7B,qBVlLsB;EUmLtB,cVnLsB;AC86B9B;;ASz3BA;EAmIU,yBVxLoB;EUyLpB,qBVzLoB;EU0LpB,WC9GM;AVw2BhB;;AS/3BA;EAwIY,gEAA8D;AT2vB1E;;ASn4BA;EA8Ic,0DAA4E;ATyvB1F;;ASv4BA;;EAiJU,6BAA6B;EAC7B,qBVvMoB;EUwMpB,gBAAgB;EAChB,cVzMoB;ACo8B9B;;AS/4BA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV83BhB;;ASr5BA;EA6JU,sBCtIM;EDuIN,cVnNoB;AC+8B9B;;AS15BA;EAqKc,gEAA8D;ATyvB5E;;AS95BA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV+4BhB;;ASt6BA;EAoFM,yBV3H4B;EU4H5B,yBAAyB;EACzB,WC/DU;AVq5BhB;;AS56BA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AV25BhB;;ASl7BA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVg6BhB;;ASv7BA;EAiGU,iDVxIwB;ACk+BlC;;AS37BA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AV06BhB;;ASj8BA;;EAyGQ,yBVhJ0B;EUiJ1B,yBAAyB;EACzB,gBAAgB;AT61BxB;;ASx8BA;EA6GQ,sBCtFQ;EDuFR,cVrJ0B;ACo/BlC;;AS78BA;EAiHU,yBC/DuB;AV+5BjC;;ASj9BA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV9JwB;ACggClC;;ASz9BA;EA0HU,0DAA4E;ATm2BtF;;AS79BA;EA4HQ,6BAA6B;EAC7B,qBVpK0B;EUqK1B,cVrK0B;AC0gClC;;ASn+BA;EAmIU,yBV1KwB;EU2KxB,qBV3KwB;EU4KxB,WC9GM;AVk9BhB;;ASz+BA;EAwIY,gEAA8D;ATq2B1E;;AS7+BA;EA8Ic,0DAA4E;ATm2B1F;;ASj/BA;;EAiJU,6BAA6B;EAC7B,qBVzLwB;EU0LxB,gBAAgB;EAChB,cV3LwB;ACgiClC;;ASz/BA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVw+BhB;;AS//BA;EA6JU,sBCtIM;EDuIN,cVrMwB;AC2iClC;;ASpgCA;EAqKc,gEAA8D;ATm2B5E;;ASxgCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVy/BhB;;AShhCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV8+BrE;;ASrhCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVo/BrE;;AS3hCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AV0/BrE;;ASjiCA;EAoFM,yBVzH4B;EU0H5B,yBAAyB;EACzB,WC/DU;AVghChB;;ASviCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVshChB;;AS7iCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AV2hChB;;ASljCA;EAiGU,iDVtIwB;AC2lClC;;AStjCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVqiChB;;AS5jCA;;EAyGQ,yBV9I0B;EU+I1B,yBAAyB;EACzB,gBAAgB;ATw9BxB;;ASnkCA;EA6GQ,sBCtFQ;EDuFR,cVnJ0B;AC6mClC;;ASxkCA;EAiHU,yBC/DuB;AV0hCjC;;AS5kCA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV5JwB;ACynClC;;ASplCA;EA0HU,0DAA4E;AT89BtF;;ASxlCA;EA4HQ,6BAA6B;EAC7B,qBVlK0B;EUmK1B,cVnK0B;ACmoClC;;AS9lCA;EAmIU,yBVxKwB;EUyKxB,qBVzKwB;EU0KxB,WC9GM;AV6kChB;;ASpmCA;EAwIY,gEAA8D;ATg+B1E;;ASxmCA;EA8Ic,0DAA4E;AT89B1F;;AS5mCA;;EAiJU,6BAA6B;EAC7B,qBVvLwB;EUwLxB,gBAAgB;EAChB,cVzLwB;ACypClC;;ASpnCA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVmmChB;;AS1nCA;EA6JU,sBCtIM;EDuIN,cVnMwB;ACoqClC;;AS/nCA;EAqKc,gEAA8D;AT89B5E;;ASnoCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVonChB;;AS3oCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVymCrE;;AShpCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV+mCrE;;AStpCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVqnCrE;;AS5pCA;EAoFM,yBV1H4B;EU2H5B,yBAAyB;EACzB,WC/DU;AV2oChB;;ASlqCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVipChB;;ASxqCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVspChB;;AS7qCA;EAiGU,kDVvIwB;ACutClC;;ASjrCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVgqChB;;ASvrCA;;EAyGQ,yBV/I0B;EUgJ1B,yBAAyB;EACzB,gBAAgB;ATmlCxB;;AS9rCA;EA6GQ,sBCtFQ;EDuFR,cVpJ0B;ACyuClC;;ASnsCA;EAiHU,yBC/DuB;AVqpCjC;;ASvsCA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV7JwB;ACqvClC;;AS/sCA;EA0HU,0DAA4E;ATylCtF;;ASntCA;EA4HQ,6BAA6B;EAC7B,qBVnK0B;EUoK1B,cVpK0B;AC+vClC;;ASztCA;EAmIU,yBVzKwB;EU0KxB,qBV1KwB;EU2KxB,WC9GM;AVwsChB;;AS/tCA;EAwIY,gEAA8D;AT2lC1E;;ASnuCA;EA8Ic,0DAA4E;ATylC1F;;ASvuCA;;EAiJU,6BAA6B;EAC7B,qBVxLwB;EUyLxB,gBAAgB;EAChB,cV1LwB;ACqxClC;;AS/uCA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV8tChB;;ASrvCA;EA6JU,sBCtIM;EDuIN,cVpMwB;ACgyClC;;AS1vCA;EAqKc,gEAA8D;ATylC5E;;AS9vCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV+uChB;;AStwCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVouCrE;;AS3wCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV0uCrE;;ASjxCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVgvCrE;;ASvxCA;EAoFM,yBV5H4B;EU6H5B,yBAAyB;EACzB,WC/DU;AVswChB;;AS7xCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AV4wChB;;ASnyCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVixChB;;ASxyCA;EAiGU,kDVzIwB;ACo1ClC;;AS5yCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AV2xChB;;ASlzCA;;EAyGQ,yBVjJ0B;EUkJ1B,yBAAyB;EACzB,gBAAgB;AT8sCxB;;ASzzCA;EA6GQ,sBCtFQ;EDuFR,cVtJ0B;ACs2ClC;;AS9zCA;EAiHU,yBC/DuB;AVgxCjC;;ASl0CA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV/JwB;ACk3ClC;;AS10CA;EA0HU,0DAA4E;ATotCtF;;AS90CA;EA4HQ,6BAA6B;EAC7B,qBVrK0B;EUsK1B,cVtK0B;AC43ClC;;ASp1CA;EAmIU,yBV3KwB;EU4KxB,qBV5KwB;EU6KxB,WC9GM;AVm0ChB;;AS11CA;EAwIY,gEAA8D;ATstC1E;;AS91CA;EA8Ic,0DAA4E;ATotC1F;;ASl2CA;;EAiJU,6BAA6B;EAC7B,qBV1LwB;EU2LxB,gBAAgB;EAChB,cV5LwB;ACk5ClC;;AS12CA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVy1ChB;;ASh3CA;EA6JU,sBCtIM;EDuIN,cVtMwB;AC65ClC;;ASr3CA;EAqKc,gEAA8D;ATotC5E;;ASz3CA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV02ChB;;ASj4CA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV+1CrE;;ASt4CA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVq2CrE;;AS54CA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AV22CrE;;ASl5CA;EAoFM,yBV7H4B;EU8H5B,yBAAyB;EACzB,yBCjEe;AVm4CrB;;ASx5CA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,yBCtEa;AVy4CrB;;AS95CA;EA8FQ,yBAAyB;EACzB,yBC1Ea;AV84CrB;;ASn6CA;EAiGU,mDV1IwB;ACg9ClC;;ASv6CA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,yBCjFa;AVw5CrB;;AS76CA;;EAyGQ,yBVlJ0B;EUmJ1B,yBAAyB;EACzB,gBAAgB;ATy0CxB;;ASp7CA;EA6GQ,oCCxFa;EDyFb,cVvJ0B;ACk+ClC;;ASz7CA;EAiHU,oCC/DuB;AV24CjC;;AS77CA;;EAoHU,oCC/FW;EDgGX,yBAAyB;EACzB,gBAAgB;EAChB,cVhKwB;AC8+ClC;;ASr8CA;EA0HU,sFAA4E;AT+0CtF;;ASz8CA;EA4HQ,6BAA6B;EAC7B,qBVtK0B;EUuK1B,cVvK0B;ACw/ClC;;AS/8CA;EAmIU,yBV5KwB;EU6KxB,qBV7KwB;EU8KxB,yBChHW;AVg8CrB;;ASr9CA;EAwIY,gEAA8D;ATi1C1E;;ASz9CA;EA8Ic,sFAA4E;AT+0C1F;;AS79CA;;EAiJU,6BAA6B;EAC7B,qBV3LwB;EU4LxB,gBAAgB;EAChB,cV7LwB;AC8gDlC;;ASr+CA;EAsJQ,6BAA6B;EAC7B,gCClIa;EDmIb,yBCnIa;AVs9CrB;;AS3+CA;EA6JU,oCCxIW;EDyIX,cVvMwB;ACyhDlC;;ASh/CA;EAqKc,gEAA8D;AT+0C5E;;ASp/CA;;EAwKU,6BAA6B;EAC7B,gCCpJW;EDqJX,gBAAgB;EAChB,yBCtJW;AVu+CrB;;AS5/CA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV09CrE;;ASjgDA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVg+CrE;;ASvgDA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVs+CrE;;AS7gDA;EAoFM,yBVvH2B;EUwH3B,yBAAyB;EACzB,WC/DU;AV4/ChB;;ASnhDA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVkgDhB;;ASzhDA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVugDhB;;AS9hDA;EAiGU,kDVpIuB;ACqkDjC;;ASliDA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVihDhB;;ASxiDA;;EAyGQ,yBV5IyB;EU6IzB,yBAAyB;EACzB,gBAAgB;ATo8CxB;;AS/iDA;EA6GQ,sBCtFQ;EDuFR,cVjJyB;ACulDjC;;ASpjDA;EAiHU,yBC/DuB;AVsgDjC;;ASxjDA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV1JuB;ACmmDjC;;AShkDA;EA0HU,0DAA4E;AT08CtF;;ASpkDA;EA4HQ,6BAA6B;EAC7B,qBVhKyB;EUiKzB,cVjKyB;AC6mDjC;;AS1kDA;EAmIU,yBVtKuB;EUuKvB,qBVvKuB;EUwKvB,WC9GM;AVyjDhB;;AShlDA;EAwIY,gEAA8D;AT48C1E;;ASplDA;EA8Ic,0DAA4E;AT08C1F;;ASxlDA;;EAiJU,6BAA6B;EAC7B,qBVrLuB;EUsLvB,gBAAgB;EAChB,cVvLuB;ACmoDjC;;AShmDA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV+kDhB;;AStmDA;EA6JU,sBCtIM;EDuIN,cVjMuB;AC8oDjC;;AS3mDA;EAqKc,gEAA8D;AT08C5E;;AS/mDA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVgmDhB;;ASvnDA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVqlDrE;;AS5nDA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV2lDrE;;ASloDA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVimDrE;;ASxoDA;EARE,kBVbc;ACiqDhB;;AStpDE;EACE,kBVkBc;ACuoDlB;;AShpDA;EANE,eVhBW;AC0qDb;;ASppDA;EAJE,kBVnBc;AC+qDhB;;ASxpDA;EAFE,iBVtBa;ACorDf;;AS5pDA;;EAyMI,uBVrP2B;EUsP3B,qBV3P0B;EU4P1B,gBAhOyB;EAiOzB,YAhOyB;ATwrD7B;;ASpqDA;EA8MI,aAAa;EACb,WAAW;AT09Cf;;ASzqDA;EAiNI,6BAA6B;EAC7B,oBAAoB;AT49CxB;;AS9qDA;ERlDE,kBAAkB;EAKhB,6BAAmC;EACnC,4BAAkC;EQkQhC,6BAA6B;AT+9CnC;;ASrrDA;EAwNI,4BVtQ0B;EUuQ1B,qBV1Q0B;EU2Q1B,cV7Q0B;EU8Q1B,gBAAgB;EAChB,oBAAoB;ATi+CxB;;AS7rDA;EA8NI,qBVlNmB;EUmNnB,gCAA0D;EAC1D,iCAA2D;ATm+C/D;;ASj+CA;EACE,mBAAmB;EACnB,aAAa;EACb,eAAe;EACf,2BAA2B;ATo+C7B;;ASx+CA;EAMI,qBAAqB;ATs+CzB;;AS5+CA;ERnII,mBQ2IwC;ATw+C5C;;ASh/CA;EAUI,sBAAsB;AT0+C1B;;ASp/CA;EAYI,mBAAmB;AT4+CvB;;ASx/CA;EA1OE,kBVbc;ACmvDhB;;ASxuDE;EACE,kBVkBc;ACytDlB;;AShgDA;EAtOE,kBVnBc;AC6vDhB;;ASpgDA;EApOE,iBVtBa;ACkwDf;;ASxgDA;EA0BQ,4BAA4B;EAC5B,yBAAyB;ATk/CjC;;AS7gDA;EA6BQ,6BAA6B;EAC7B,0BAA0B;ERjK9B,iBQkKwC;ATo/C5C;;ASnhDA;ERnII,cQoKqC;ATs/CzC;;ASvhDA;EAoCQ,UAAU;ATu/ClB;;AS3hDA;EA0CQ,UAAU;ATq/ClB;;AS/hDA;EA4CU,UAAU;ATu/CpB;;ASniDA;EA8CQ,YAAY;EACZ,cAAc;ATy/CtB;;ASxiDA;EAiDI,uBAAuB;AT2/C3B;;AS5iDA;EAoDQ,oBAAoB;EACpB,qBAAqB;AT4/C7B;;ASjjDA;EAuDI,yBAAyB;AT8/C7B;;ASrjDA;EA0DQ,oBAAoB;EACpB,qBAAqB;AT+/C7B;;AWl1DA;EACE,YAAY;EACZ,cAAc;EACd,kBAAkB;EAClB,WA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wB;EgBsCxB,WLsCU;AVovEhB;;Ae3zEA;EAgCM,yBhBvB4B;EgBwB5B,WLsCU;AVyvEhB;;Aeh0EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AV8uErE;;Aer0EA;EAgCM,yBhBrB4B;EgBsB5B,WLsCU;AVmwEhB;;Ae10EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVwvErE;;Ae/0EA;EAgCM,yBhBtB4B;EgBuB5B,WLsCU;AV6wEhB;;Aep1EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVkwErE;;Aez1EA;EAgCM,yBhBxB4B;EgByB5B,WLsCU;AVuxEhB;;Ae91EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AV4wErE;;Aen2EA;EAgCM,yBhBzB4B;EgB0B5B,yBLoCe;AVmyErB;;Aex2EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVsxErE;;Ae72EA;EAgCM,yBhBnB2B;EgBoB3B,WLsCU;AV2yEhB;;Ael3EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVgyErE;;AgBx3EA;EAEE,qBAAqB;EACrB,wBAAwB;EACxB,YAAY;EACZ,qBjBwDqB;EiBvDrB,cAAc;EACd,YjBoBW;EiBnBX,gBAAgB;EAChB,UAAU;EACV,WAAW;AhB03Eb;;AgBp4EA;EAYI,yBjBX2B;ACu4E/B;;AgBx4EA;EAcI,yBjBjB0B;AC+4E9B;;AgB54EA;EAgBI,yBjBnB0B;ACm5E9B;;AgBh5EA;EAkBI,yBjBrB0B;EiBsB1B,YAAY;AhBk4EhB;;AgBr5EA;EAyBQ,uBjBpBuB;ACo5E/B;;AgBz5EA;EA2BQ,uBjBtBuB;ACw5E/B;;AgB75EA;EA6BQ,uBjBxBuB;AC45E/B;;AgBj6EA;EA+BQ,mEAA2F;AhBs4EnG;;AgBr6EA;EAyBQ,yBjBjCqB;ACi7E7B;;AgBz6EA;EA2BQ,yBjBnCqB;ACq7E7B;;AgB76EA;EA6BQ,yBjBrCqB;ACy7E7B;;AgBj7EA;EA+BQ,qEAA2F;AhBs5EnG;;AgBr7EA;EAyBQ,4BjBtBsB;ACs7E9B;;AgBz7EA;EA2BQ,4BjBxBsB;AC07E9B;;AgB77EA;EA6BQ,4BjB1BsB;AC87E9B;;AgBj8EA;EA+BQ,wEAA2F;AhBs6EnG;;AgBr8EA;EAyBQ,yBjB7BsB;AC68E9B;;AgBz8EA;EA2BQ,yBjB/BsB;ACi9E9B;;AgB78EA;EA6BQ,yBjBjCsB;ACq9E9B;;AgBj9EA;EA+BQ,qEAA2F;AhBs7EnG;;AgBr9EA;EAyBQ,yBjBf0B;AC+8ElC;;AgBz9EA;EA2BQ,yBjBjB0B;ACm9ElC;;AgB79EA;EA6BQ,yBjBnB0B;ACu9ElC;;AgBj+EA;EA+BQ,qEAA2F;AhBs8EnG;;AgBr+EA;EAyBQ,yBjBb0B;AC69ElC;;AgBz+EA;EA2BQ,yBjBf0B;ACi+ElC;;AgB7+EA;EA6BQ,yBjBjB0B;ACq+ElC;;AgBj/EA;EA+BQ,qEAA2F;AhBs9EnG;;AgBr/EA;EAyBQ,yBjBd0B;AC8+ElC;;AgBz/EA;EA2BQ,yBjBhB0B;ACk/ElC;;AgB7/EA;EA6BQ,yBjBlB0B;ACs/ElC;;AgBjgFA;EA+BQ,qEAA2F;AhBs+EnG;;AgBrgFA;EAyBQ,yBjBhB0B;ACggFlC;;AgBzgFA;EA2BQ,yBjBlB0B;ACogFlC;;AgB7gFA;EA6BQ,yBjBpB0B;ACwgFlC;;AgBjhFA;EA+BQ,qEAA2F;AhBs/EnG;;AgBrhFA;EAyBQ,yBjBjB0B;ACihFlC;;AgBzhFA;EA2BQ,yBjBnB0B;ACqhFlC;;AgB7hFA;EA6BQ,yBjBrB0B;ACyhFlC;;AgBjiFA;EA+BQ,qEAA2F;AhBsgFnG;;AgBriFA;EAyBQ,yBjBXyB;AC2hFjC;;AgBziFA;EA2BQ,yBjBbyB;AC+hFjC;;AgB7iFA;EA6BQ,yBjBfyB;ACmiFjC;;AgBjjFA;EA+BQ,qEAA2F;AhBshFnG;;AgBrjFA;EAkCI,gCAtCkC;UAsClC,wBAtCkC;EAuClC,2CAAmC;UAAnC,mCAAmC;EACnC,yCAAiC;UAAjC,iCAAiC;EACjC,yCAAiC;UAAjC,iCAAiC;EACjC,yBjBrC2B;EiBsC3B,qEAA0F;EAC1F,6BAA6B;EAC7B,4BAA4B;EAC5B,0BAA0B;AhBuhF9B;;AgBjkFA;EA4CM,6BAA6B;AhByhFnC;;AgBrkFA;EA8CM,6BAA6B;AhB2hFnC;;AgBzkFA;EAgDM,oBAAoB;AhB6hF1B;;AgB7kFA;EAoDI,ejBxBY;ACqjFhB;;AgBjlFA;EAsDI,ejB5BY;AC2jFhB;;AgBrlFA;EAwDI,cjB/BW;ACgkFf;;AgB/hFA;EACE;IACE,2BAA2B;EhBkiF7B;EgBjiFA;IACE,4BAA4B;EhBmiF9B;AACF;;AgBxiFA;EACE;IACE,2BAA2B;EhBkiF7B;EgBjiFA;IACE,4BAA4B;EhBmiF9B;AACF;;AiB/kFA;EAEE,uBlBhB6B;EkBiB7B,clB1B4B;AC2mF9B;;AiBplFA;;EAMI,yBlBzB0B;EkB0B1B,qBA9B6B;EA+B7B,qBA9B6B;EA+B7B,mBAAmB;AjBmlFvB;;AiB5lFA;;EAeQ,uBlB7BuB;EkB8BvB,mBlB9BuB;EkB+BvB,clB5CqB;AC8nF7B;;AiBnmFA;;EAeQ,yBlB1CqB;EkB2CrB,qBlB3CqB;EkB4CrB,YlB/BuB;ACwnF/B;;AiB1mFA;;EAeQ,4BlB/BsB;EkBgCtB,wBlBhCsB;EkBiCtB,yBPkCa;AV8jFrB;;AiBjnFA;;EAeQ,yBlBtCsB;EkBuCtB,qBlBvCsB;EkBwCtB,WPoCQ;AVmkFhB;;AiBxnFA;;EAeQ,yBlBxB0B;EkByB1B,qBlBzB0B;EkB0B1B,WPoCQ;AV0kFhB;;AiB/nFA;;EAeQ,yBlBtB0B;EkBuB1B,qBlBvB0B;EkBwB1B,WPoCQ;AVilFhB;;AiBtoFA;;EAeQ,yBlBvB0B;EkBwB1B,qBlBxB0B;EkByB1B,WPoCQ;AVwlFhB;;AiB7oFA;;EAeQ,yBlBzB0B;EkB0B1B,qBlB1B0B;EkB2B1B,WPoCQ;AV+lFhB;;AiBppFA;;EAeQ,yBlB1B0B;EkB2B1B,qBlB3B0B;EkB4B1B,yBPkCa;AVwmFrB;;AiB3pFA;;EAeQ,yBlBpByB;EkBqBzB,qBlBrByB;EkBsBzB,WPoCQ;AV6mFhB;;AiBlqFA;;EAoBM,mBAAmB;EACnB,SAAS;AjBmpFf;;AiBxqFA;;EAuBM,yBlBhC4B;EkBiC5B,WP6BU;AVynFhB;;AiB9qFA;;;;EA2BQ,mBAAmB;AjB0pF3B;;AiBrrFA;;EA6BM,sBAAsB;AjB6pF5B;;AiB1rFA;EA+BI,clBtD0B;ACqtF9B;;AiB9rFA;EAiCM,mBAAmB;AjBiqFzB;;AiBlsFA;EAoCM,yBlB7C4B;EkB8C5B,WPgBU;AVkpFhB;;AiBvsFA;;EAwCQ,mBAAmB;AjBoqF3B;;AiB5sFA;;EA2CQ,kBPUQ;EOTR,mBAAmB;AjBsqF3B;;AiBltFA;EA8CI,6BA5DqC;AjBouFzC;;AiBttFA;;EAiDM,qBApEgC;EAqEhC,clBzEwB;ACmvF9B;;AiB5tFA;EAoDI,6BAhEqC;AjB4uFzC;;AiBhuFA;;EAuDM,qBAxEgC;EAyEhC,clB/EwB;AC6vF9B;;AiBtuFA;EA0DI,6BAvEqC;AjBuvFzC;;AiB1uFA;;EA+DU,sBAAsB;AjBgrFhC;;AiB/uFA;;EAoEM,iBAAiB;AjBgrFvB;;AiBpvFA;;EAyEU,wBAAwB;AjBgrFlC;;AiBzvFA;EA2EI,WAAW;AjBkrFf;;AiB7vFA;EAgFU,yBlB/FoB;ACgxF9B;;AiBjwFA;EAqFY,yBlBpGkB;ACoxF9B;;AiBrwFA;EAuFc,4BlBvGgB;ACyxF9B;;AiBzwFA;;EA2FM,qBAAqB;AjBmrF3B;;AiB9wFA;EAgGU,yBlB/GoB;ACiyF9B;;AiBhrFA;EhBjEE,iCAAiC;EgBoEjC,cAAc;EACd,kBAAkB;EAClB,eAAe;AjBkrFjB;;AkB7yFA;EACE,mBAAmB;EACnB,aAAa;EACb,eAAe;EACf,2BAA2B;AlBgzF7B;;AkBpzFA;EAMI,qBAAqB;AlBkzFzB;;AkBxzFA;EjBiJI,mBiBzIwC;AlBozF5C;;AkB5zFA;EAUI,sBAAsB;AlBszF1B;;AkBh0FA;EAYI,mBAAmB;AlBwzFvB;;AkBp0FA;EAgBM,enBYO;AC4yFb;;AkBx0FA;EAmBM,kBnBQU;ACizFhB;;AkB50FA;EAqBI,uBAAuB;AlB2zF3B;;AkBh1FA;EAuBM,qBAAqB;EACrB,oBAAoB;AlB6zF1B;;AkBr1FA;EA0BI,yBAAyB;AlB+zF7B;;AkBz1FA;EA6BQ,mBAAmB;AlBg0F3B;;AkB71FA;EA+BQ,eAAe;AlBk0FvB;;AkBj2FA;EjBiJI,ciB/GmC;AlBm0FvC;;AkBr2FA;EjBiJI,eiB7GqC;EAK/B,0BAA0B;EAC1B,6BAA6B;AlBi0FvC;;AkB32FA;EAgDU,yBAAyB;EACzB,4BAA4B;AlB+zFtC;;AkB7zFA;EACE,mBAAmB;EACnB,4BnBjD4B;EmBkD5B,kBnBMU;EmBLV,cnBzD4B;EmB0D5B,oBAAoB;EACpB,kBnB5Bc;EmB6Bd,WAAW;EACX,uBAAuB;EACvB,gBAAgB;EAChB,oBAAoB;EACpB,qBAAqB;EACrB,mBAAmB;AlBg0FrB;;AkB50FA;EjB8FI,qBiBhFuC;EjBgFvC,sBiB/EyC;AlBk0F7C;;AkBj1FA;EAqBM,uBnBlEyB;EmBmEzB,cnBhFuB;ACg5F7B;;AkBt1FA;EAqBM,yBnB/EuB;EmBgFvB,YnBnEyB;ACw4F/B;;AkB31FA;EAqBM,4BnBpEwB;EmBqExB,yBRFe;AV40FrB;;AkBh2FA;EAqBM,yBnB3EwB;EmB4ExB,WRAU;AV+0FhB;;AkBr2FA;EAqBM,yBnB7D4B;EmB8D5B,WRAU;AVo1FhB;;AkB12FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVy0FrE;;AkB/2FA;EAqBM,yBnB3D4B;EmB4D5B,WRAU;AV81FhB;;AkBp3FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVm1FrE;;AkBz3FA;EAqBM,yBnB5D4B;EmB6D5B,WRAU;AVw2FhB;;AkB93FA;EA4BU,yBRCsC;EQAtC,cRS2D;AV61FrE;;AkBn4FA;EAqBM,yBnB9D4B;EmB+D5B,WRAU;AVk3FhB;;AkBx4FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVu2FrE;;AkB74FA;EAqBM,yBnB/D4B;EmBgE5B,yBRFe;AV83FrB;;AkBl5FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVi3FrE;;AkBv5FA;EAqBM,yBnBzD2B;EmB0D3B,WRAU;AVs4FhB;;AkB55FA;EA4BU,yBRCsC;EQAtC,cRS2D;AV23FrE;;AkBj6FA;EAgCI,kBnBtDY;AC27FhB;;AkBr6FA;EAkCI,enBzDS;ACg8Fb;;AkBz6FA;EAoCI,kBnB5DY;ACq8FhB;;AkB76FA;EjB8FI,sBiBvD0C;EjBuD1C,qBiBtD0C;AlB04F9C;;AkBl7FA;EjB8FI,sBiBpD0C;EjBoD1C,qBiBnD0C;AlB44F9C;;AkBv7FA;EjB8FI,sBiBjD0C;EjBiD1C,qBiBhD0C;AlB84F9C;;AkB57FA;EjB8FI,iBiBrJmB;EAyGnB,UAAU;EACV,kBAAkB;EAClB,UAAU;AlB+4Fd;;AkBn8FA;EAuDM,8BAA8B;EAC9B,WAAW;EACX,cAAc;EACd,SAAS;EACT,kBAAkB;EAClB,QAAQ;EACR,0DAA0D;EAC1D,+BAA+B;AlBg5FrC;;AkB98FA;EAgEM,WAAW;EACX,UAAU;AlBk5FhB;;AkBn9FA;EAmEM,WAAW;EACX,UAAU;AlBo5FhB;;AkBx9FA;EAuEM,yBAAmD;AlBq5FzD;;AkB59FA;EAyEM,yBAAoD;AlBu5F1D;;AkBh+FA;EA2EI,qBnBhEmB;ACy9FvB;;AkBv5FA;EAEI,0BAA0B;AlBy5F9B;;AmB/gGA;;EAGE,sBAAsB;AnBihGxB;;AmBphGA;;;;EAMI,oBAAoB;AnBqhGxB;;AmB3hGA;;EAQI,iBApBmB;AnB4iGvB;;AmBhiGA;;EAUI,iBArBmB;AnBgjGvB;;AmBriGA;;EAYI,sBAAsB;AnB8hG1B;;AmB5hGA;EACE,cpB9B4B;EoBiC5B,epBLW;EoBMX,gBpBGmB;EoBFnB,kBAnCuB;AnBgkGzB;;AmBniGA;EAQI,cApCwB;EAqCxB,oBApCyB;AnBmkG7B;;AmBxiGA;EAWI,oBA3B+B;AnB4jGnC;;AmB5iGA;EAgBM,epBnBO;ACmjGb;;AmBhjGA;EAgBM,iBpBlBS;ACsjGf;;AmBpjGA;EAgBM,epBjBO;ACyjGb;;AmBxjGA;EAgBM,iBpBhBS;AC4jGf;;AmB5jGA;EAgBM,kBpBfU;AC+jGhB;;AmBhkGA;EAgBM,epBdO;ACkkGb;;AmBpkGA;EAgBM,kBpBbU;ACqkGhB;;AmBtjGA;EACE,cpB/C4B;EoBkD5B,kBpBrBc;EoBsBd,gBpBjBiB;EoBkBjB,iBA3CyB;AnBkmG3B;;AmB7jGA;EAQI,cpBvD0B;EoBwD1B,gBpBnBiB;AC4kGrB;;AmBlkGA;EAWI,oBA7C+B;AnBwmGnC;;AmBtkGA;EAgBM,epBrCO;AC+lGb;;AmB1kGA;EAgBM,iBpBpCS;ACkmGf;;AmB9kGA;EAgBM,epBnCO;ACqmGb;;AmBllGA;EAgBM,iBpBlCS;ACwmGf;;AmBtlGA;EAgBM,kBpBjCU;AC2mGhB;;AmB1lGA;EAgBM,epBhCO;AC8mGb;;AmB9lGA;EAgBM,kBpB/BU;ACinGhB;;AoB/oGA;EACE,cAAc;EACd,eAAe;EACf,mBAAmB;EACnB,kBAAkB;EAClB,yBAAyB;ApBkpG3B;;AoB7oGA;EACE,mBAAmB;EACnB,4BrBP4B;EqBQ5B,qBrBkDqB;EqBjDrB,oBAAoB;EACpB,kBrBac;EqBZd,WAAW;EACX,uBAAuB;EACvB,oBAAoB;EACpB,gBAAgB;EAChB,uBAAuB;EACvB,kBAAkB;EAClB,mBAAmB;ApBgpGrB;;AqB9qGA,eAAA;AC0DA;EAxBE,uBvBnB6B;EuBoB7B,qBvBzB4B;EuB0B5B,kBvBiCU;EuBhCV,cvB/B4B;ACgrG9B;;ACnnGI;EqB5BA,4BvBjC0B;ACorG9B;;ACvnGI;EqB5BA,4BvBjC0B;ACwrG9B;;AC3nGI;EqB5BA,4BvBjC0B;AC4rG9B;;AC/nGI;EqB5BA,4BvBjC0B;ACgsG9B;;AsB9pGE;EAEE,qBvBjC0B;ACisG9B;;AsB/pGE;EAIE,qBvBzB8B;EuB0B9B,iDvB1B8B;ACyrGlC;;AsB9pGE;;;;;EAEE,4BvBtC0B;EuBuC1B,wBvBvC0B;EuBwC1B,gBAAgB;EAChB,cvB9C0B;ACktG9B;;ACvpGI;;;;;EqBXE,+BvBhDwB;AC0tG9B;;AC/pGI;;;;;EqBXE,+BvBhDwB;ACkuG9B;;ACvqGI;;;;;EqBXE,+BvBhDwB;AC0uG9B;;AC/qGI;;;;;EqBXE,+BvBhDwB;ACkvG9B;;AuBpvGA;EAEE,2DxBN2B;EwBO3B,eAAe;EACf,WAAW;AvBsvGb;;AuBrvGE;EACE,gBAAgB;AvBwvGpB;;AuBpvGI;EACE,mBxBFyB;ACyvG/B;;AuBxvGK;EAMG,mDxBPuB;AC6vG/B;;AuB5vGI;EACE,qBxBfuB;AC8wG7B;;AuBhwGK;EAMG,gDxBpBqB;ACkxG7B;;AuBpwGI;EACE,wBxBJwB;AC2wG9B;;AuBxwGK;EAMG,mDxBTsB;AC+wG9B;;AuB5wGI;EACE,qBxBXwB;AC0xG9B;;AuBhxGK;EAMG,gDxBhBsB;AC8xG9B;;AuBpxGI;EACE,qBxBG4B;ACoxGlC;;AuBxxGK;EAMG,iDxBF0B;ACwxGlC;;AuB5xGI;EACE,qBxBK4B;AC0xGlC;;AuBhyGK;EAMG,iDxBA0B;AC8xGlC;;AuBpyGI;EACE,qBxBI4B;ACmyGlC;;AuBxyGK;EAMG,kDxBD0B;ACuyGlC;;AuB5yGI;EACE,qBxBE4B;AC6yGlC;;AuBhzGK;EAMG,kDxBH0B;ACizGlC;;AuBpzGI;EACE,qBxBC4B;ACszGlC;;AuBxzGK;EAMG,mDxBJ0B;AC0zGlC;;AuB5zGI;EACE,qBxBO2B;ACwzGjC;;AuBh0GK;EAMG,kDxBEyB;AC4zGjC;;AuB5zGE;EzBmBA,kBCyBgB;EDxBhB,kBCNc;ACmzGhB;;AuB/zGE;EzBoBA,kBCVc;ACyzGhB;;AuBj0GE;EzBoBA,iBCba;AC8zGf;;AuBl0GE;EACE,cAAc;EACd,WAAW;AvBq0Gf;;AuBp0GE;EACE,eAAe;EACf,WAAW;AvBu0Gf;;AuBr0GA;EAGI,qBxB8BmB;EwB7BnB,gDAA4D;EAC5D,iDAA6D;AvBs0GjE;;AuB30GA;EAOI,6BAA6B;EAC7B,yBAAyB;EACzB,gBAAgB;EAChB,eAAe;EACf,gBAAgB;AvBw0GpB;;AuBt0GA;EAEE,cAAc;EACd,eAAe;EACf,eAAe;EACf,2BzB7CkE;EyB8ClE,gBAAgB;AvBw0GlB;;AuB90GA;EAQI,gBA1DsB;EA2DtB,eA1DqB;AvBo4GzB;;AuBn1GA;EAWI,eAAe;AvB40GnB;;AuBv1GA;EAcI,YAAY;AvB60GhB;;AwB94GA;EACE,eAAe;EACf,qBAAqB;EACrB,iBAAiB;EACjB,kBAAkB;AxBi5GpB;;AwBh5GE;EACE,eAAe;AxBm5GnB;;AwBl5GE;EACE,czBF0B;ACu5G9B;;AwBp5GE;;;;;EAGE,czBJ0B;EyBK1B,mBAAmB;AxBy5GvB;;AwBp5GA;EvBwII,mBuBrIqC;AxBq5GzC;;AyBx6GA;EACE,qBAAqB;EACrB,eAAe;EACf,kBAAkB;EAClB,mBAAmB;AzB26GrB;;AyB/6GA;EAMI,a3BDkB;AE86GtB;;AyBn7GA;EAUM,qB1BU4B;EE4I9B,awBrJ+B;EAC7B,UAAU;AzB66GhB;;AyBz7GA;EAeM,qB1BsDiB;EEmFnB,kBwBxIsC;AzB86G1C;;AyB97GA;EAmBI,eAAe;EACf,cAAc;EACd,cAAc;EACd,eAAe;EACf,aAAa;AzB+6GjB;;AyBt8GA;EAyBM,aAAa;AzBi7GnB;;AyB18GA;;EA4BM,wB1BjBwB;ACo8G9B;;AyB/8GA;ExBwJI,mBwB1HwC;AzBq7G5C;;AyBn9GA;EAgCM,YAAY;EACZ,UAAU;AzBu7GhB;;AyBx9GA;EAmCQ,kBAAkB;AzBy7G1B;;AyB59GA;EAuCM,qB1BnCwB;AC49G9B;;AyBh+GA;EA6CQ,mB1BhCuB;ACu9G/B;;AyBp+GA;EA+CQ,mB1BlCuB;AC29G/B;;AyBx+GA;EAkDU,qBfyDuB;AVi4GjC;;AyB5+GA;EAuDU,mD1B1CqB;ACm+G/B;;AyBh/GA;EA6CQ,qB1B7CqB;ACo/G7B;;AyBp/GA;EA+CQ,qB1B/CqB;ACw/G7B;;AyBx/GA;EAkDU,mBfyDuB;AVi5GjC;;AyB5/GA;EAuDU,gD1BvDmB;ACggH7B;;AyBhgHA;EA6CQ,wB1BlCsB;ACy/G9B;;AyBpgHA;EA+CQ,wB1BpCsB;AC6/G9B;;AyBxgHA;EAkDU,qBfyDuB;AVi6GjC;;AyB5gHA;EAuDU,mD1B5CoB;ACqgH9B;;AyBhhHA;EA6CQ,qB1BzCsB;ACghH9B;;AyBphHA;EA+CQ,qB1B3CsB;ACohH9B;;AyBxhHA;EAkDU,qBfyDuB;AVi7GjC;;AyB5hHA;EAuDU,gD1BnDoB;AC4hH9B;;AyBhiHA;EA6CQ,qB1B3B0B;ACkhHlC;;AyBpiHA;EA+CQ,qB1B7B0B;ACshHlC;;AyBxiHA;EAkDU,qBfyDuB;AVi8GjC;;AyB5iHA;EAuDU,iD1BrCwB;AC8hHlC;;AyBhjHA;EA6CQ,qB1BzB0B;ACgiHlC;;AyBpjHA;EA+CQ,qB1B3B0B;ACoiHlC;;AyBxjHA;EAkDU,qBfyDuB;AVi9GjC;;AyB5jHA;EAuDU,iD1BnCwB;AC4iHlC;;AyBhkHA;EA6CQ,qB1B1B0B;ACijHlC;;AyBpkHA;EA+CQ,qB1B5B0B;ACqjHlC;;AyBxkHA;EAkDU,qBfyDuB;AVi+GjC;;AyB5kHA;EAuDU,kD1BpCwB;AC6jHlC;;AyBhlHA;EA6CQ,qB1B5B0B;ACmkHlC;;AyBplHA;EA+CQ,qB1B9B0B;ACukHlC;;AyBxlHA;EAkDU,qBfyDuB;AVi/GjC;;AyB5lHA;EAuDU,kD1BtCwB;AC+kHlC;;AyBhmHA;EA6CQ,qB1B7B0B;AColHlC;;AyBpmHA;EA+CQ,qB1B/B0B;ACwlHlC;;AyBxmHA;EAkDU,qBfyDuB;AVigHjC;;AyB5mHA;EAuDU,mD1BvCwB;ACgmHlC;;AyBhnHA;EA6CQ,qB1BvByB;AC8lHjC;;AyBpnHA;EA+CQ,qB1BzByB;ACkmHjC;;AyBxnHA;EAkDU,qBfyDuB;AVihHjC;;AyB5nHA;EAuDU,kD1BjCuB;AC0mHjC;;AyBhoHA;E3ByCE,kBCyBgB;EDxBhB,kBCNc;ACimHhB;;AyBroHA;E3B4CE,kBCVc;ACumHhB;;AyBzoHA;E3B8CE,iBCba;AC4mHf;;AyB7oHA;EAkEM,qB1B5DwB;AC2oH9B;;AyBjpHA;EAoEI,WAAW;AzBilHf;;AyBrpHA;EAsEM,WAAW;AzBmlHjB;;AyBzpHA;EA0EM,aAAa;EACb,kBAAkB;ExBqFpB,awBpF+B;EAC7B,YAAY;EACZ,eAAe;AzBmlHrB;;AyBjqHA;EAgFM,kB1B5CU;ACioHhB;;AyBrqHA;EAkFM,kB1BhDU;ACuoHhB;;AyBzqHA;EAoFM,iB1BnDS;AC4oHf;;A0BhqHA;EAEE,oBAAoB;EACpB,aAAa;EACb,2BAA2B;EAC3B,kBAAkB;A1BkqHpB;;A0BvqHA;EAYQ,uB3BZuB;E2BavB,yBAAyB;EACzB,c3B3BqB;AC0rH7B;;A0B7qHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,c3BjCmB;ACgsH7B;;A0BnrHA;EAwBU,yBAAyB;EACzB,+C3BzBqB;E2B0BrB,c3BvCmB;ACssH7B;;A0BzrHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,c3B7CmB;AC4sH7B;;A0B/rHA;EAYQ,yB3BzBqB;E2B0BrB,yBAAyB;EACzB,Y3BduB;ACqsH/B;;A0BrsHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,Y3BpBqB;AC2sH/B;;A0B3sHA;EAwBU,yBAAyB;EACzB,4C3BtCmB;E2BuCnB,Y3B1BqB;ACitH/B;;A0BjtHA;EA8BU,uBhBgEuB;EgB/DvB,yBAAyB;EACzB,Y3BhCqB;ACutH/B;;A0BvtHA;EAYQ,4B3BdsB;E2BetB,yBAAyB;EACzB,yBhBmDa;AV4pHrB;;A0B7tHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,yBhB6CW;AVkqHrB;;A0BnuHA;EAwBU,yBAAyB;EACzB,+C3B3BoB;E2B4BpB,yBhBuCW;AVwqHrB;;A0BzuHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,yBhBiCW;AV8qHrB;;A0B/uHA;EAYQ,yB3BrBsB;E2BsBtB,yBAAyB;EACzB,WhBqDQ;AVkrHhB;;A0BrvHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwrHhB;;A0B3vHA;EAwBU,yBAAyB;EACzB,4C3BlCoB;E2BmCpB,WhByCM;AV8rHhB;;A0BjwHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVosHhB;;A0BvwHA;EAYQ,yB3BP0B;E2BQ1B,yBAAyB;EACzB,WhBqDQ;AV0sHhB;;A0B7wHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVgtHhB;;A0BnxHA;EAwBU,yBAAyB;EACzB,6C3BpBwB;E2BqBxB,WhByCM;AVstHhB;;A0BzxHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AV4tHhB;;A0B/xHA;EAYQ,yB3BL0B;E2BM1B,yBAAyB;EACzB,WhBqDQ;AVkuHhB;;A0BryHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwuHhB;;A0B3yHA;EAwBU,yBAAyB;EACzB,6C3BlBwB;E2BmBxB,WhByCM;AV8uHhB;;A0BjzHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVovHhB;;A0BvzHA;EAYQ,yB3BN0B;E2BO1B,yBAAyB;EACzB,WhBqDQ;AV0vHhB;;A0B7zHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVgwHhB;;A0Bn0HA;EAwBU,yBAAyB;EACzB,8C3BnBwB;E2BoBxB,WhByCM;AVswHhB;;A0Bz0HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AV4wHhB;;A0B/0HA;EAYQ,yB3BR0B;E2BS1B,yBAAyB;EACzB,WhBqDQ;AVkxHhB;;A0Br1HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwxHhB;;A0B31HA;EAwBU,yBAAyB;EACzB,8C3BrBwB;E2BsBxB,WhByCM;AV8xHhB;;A0Bj2HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVoyHhB;;A0Bv2HA;EAYQ,yB3BT0B;E2BU1B,yBAAyB;EACzB,yBhBmDa;AV4yHrB;;A0B72HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,yBhB6CW;AVkzHrB;;A0Bn3HA;EAwBU,yBAAyB;EACzB,+C3BtBwB;E2BuBxB,yBhBuCW;AVwzHrB;;A0Bz3HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,yBhBiCW;AV8zHrB;;A0B/3HA;EAYQ,yB3BHyB;E2BIzB,yBAAyB;EACzB,WhBqDQ;AVk0HhB;;A0Br4HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVw0HhB;;A0B34HA;EAwBU,yBAAyB;EACzB,8C3BhBuB;E2BiBvB,WhByCM;AV80HhB;;A0Bj5HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVo1HhB;;A0Bv5HA;EAmCI,kB3BZY;ACo4HhB;;A0B35HA;EAqCI,e3BfS;ACy4Hb;;A0B/5HA;EAuCI,kB3BlBY;AC84HhB;;A0Bn6HA;EA0CQ,eAAe;A1B63HvB;;A0Bv6HA;EA4CI,iB3BxBW;ACu5Hf;;A0B36HA;EA+CQ,eAAe;A1Bg4HvB;;A0B/6HA;EAmDM,6BAA6B;EAC7B,0BAA0B;A1Bg4HhC;;A0Bp7HA;EAsDM,4BAA4B;EAC5B,yBAAyB;A1Bk4H/B;;A0Bz7HA;EA0DQ,kB3BJI;ACu4HZ;;A0B77HA;EA4DQ,aAAa;A1Bq4HrB;;A0Bj8HA;EA+DM,sBAAsB;A1Bs4H5B;;A0Br8HA;EAiEM,sBAAsB;EACtB,YAAY;EACZ,gBAAgB;A1Bw4HtB;;A0B38HA;EAqEM,uBAAuB;A1B04H7B;;A0B/8HA;EAuEM,aAAa;EACb,YAAY;A1B44HlB;;A0Bp9HA;EA0EQ,eAAe;A1B84HvB;;A0Bx9HA;EA6EQ,eAAe;A1B+4HvB;;A0B59HA;EAgFQ,eAAe;A1Bg5HvB;;A0Bh+HA;EAmFQ,eAAe;A1Bi5HvB;;A0Bp+HA;EAsFQ,0BAA4C;A1Bk5HpD;;A0Bx+HA;EAwFQ,0B3BlCI;E2BmCJ,uBAAuB;A1Bo5H/B;;A0B7+HA;EA2FI,uBAAuB;A1Bs5H3B;;A0Bj/HA;EA8FM,WAAW;A1Bu5HjB;;A0Br/HA;EAgGM,YAAY;EACZ,eAAe;A1By5HrB;;A0B1/HA;EAmGI,yBAAyB;A1B25H7B;;A0B9/HA;EAqGM,0BAA4C;A1B65HlD;;A0BlgIA;EAuGM,0B3BjDM;E2BkDN,2BAA2B;EAC3B,SAAS;A1B+5Hf;;A0B75HA;EACE,oBAAoB;EACpB,aAAa;EACb,eAAe;EACf,2BAA2B;EAC3B,gBAAgB;EAChB,kBAAkB;A1Bg6HpB;;A0Bt6HA;EASM,yBhBtB2B;EgBuB3B,c3B9HwB;AC+hI9B;;A0B36HA;EAYM,qBhBzB2B;AV47HjC;;A0B/6HA;EAeM,yBhB5B2B;EgB6B3B,c3BpIwB;ACwiI9B;;A0Bp7HA;EAkBM,qBhB/B2B;AVq8HjC;;A0Bp6HA;EACE,YAAY;EACZ,OAAO;EACP,UAAU;EACV,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,WAAW;A1Bu6Hb;;A0Br6HA;;EAGE,qB3BhJ4B;E2BiJ5B,kB3BtFU;E2BuFV,cAAc;EACd,iBAAiB;EACjB,kBAAkB;EAClB,mBAAmB;A1Bu6HrB;;A0Br6HA;EACE,4B3BrJ4B;E2BsJ5B,c3B5J4B;ACokI9B;;A0Bt6HA;EACE,qB3B5J4B;E2B6J5B,mBA9J4B;EA+J5B,2BA9JoC;EA+JpC,cAAc;EACd,eA/JwB;EAgKxB,gBAAgB;EAChB,mBAAmB;EACnB,uBAAuB;A1By6HzB;;A0Bv6HA;EACE,mBAAmB;EACnB,aAAa;EACb,WAAW;EACX,uBAAuB;EzBzBrB,kByB0BmC;EACrC,UAAU;A1B06HZ;;A0Bh7HA;EAQI,eAAe;A1B46HnB;;A2B5lIA;EACE,c5BF4B;E4BG5B,cAAc;EACd,e5B2BW;E4B1BX,gB5BiCe;AC8jIjB;;A2BnmIA;EAMI,oBAAoB;A3BimIxB;;A2BvmIA;EASI,kB5BsBY;AC4kIhB;;A2B3mIA;EAWI,kB5BkBY;ACklIhB;;A2B/mIA;EAaI,iB5BeW;ACulIf;;A2BpmIA;EACE,cAAc;EACd,kB5Bcc;E4Bbd,mBAAmB;A3BumIrB;;A2B1mIA;EAOM,Y5BdyB;ACqnI/B;;A2B9mIA;EAOM,c5B3BuB;ACsoI7B;;A2BlnIA;EAOM,iB5BhBwB;AC+nI9B;;A2BtnIA;EAOM,c5BvBwB;AC0oI9B;;A2B1nIA;EAOM,c5BT4B;ACgoIlC;;A2B9nIA;EAOM,c5BP4B;ACkoIlC;;A2BloIA;EAOM,c5BR4B;ACuoIlC;;A2BtoIA;EAOM,c5BV4B;AC6oIlC;;A2B1oIA;EAOM,c5BX4B;ACkpIlC;;A2B9oIA;EAOM,c5BL2B;ACgpIjC;;A2BvoIA;EAEI,sBAAsB;A3ByoI1B;;A2B3oIA;EAKI,aAAa;EACb,2BAA2B;A3B0oI/B;;A2BhpIA;E1ByHI,iB0BhHwC;A3B2oI5C;;A2BppIA;;;EAcU,gBAAgB;A3B4oI1B;;A2B1pIA;;;EAuBY,4BAA4B;EAC5B,yBAAyB;A3ByoIrC;;A2BjqIA;;;EAiCY,6BAA6B;EAC7B,0BAA0B;A3BsoItC;;A2BxqIA;;;;;EAyCY,UAAU;A3BuoItB;;A2BhrIA;;;;;;;;;EA8CY,UAAU;A3B8oItB;;A2B5rIA;;;;;;;;;EAgDc,UAAU;A3BwpIxB;;A2BxsIA;EAkDQ,YAAY;EACZ,cAAc;A3B0pItB;;A2B7sIA;EAqDM,uBAAuB;A3B4pI7B;;A2BjtIA;EAuDM,yBAAyB;A3B8pI/B;;A2BrtIA;EA0DQ,YAAY;EACZ,cAAc;A3B+pItB;;A2B1tIA;EA6DI,aAAa;EACb,2BAA2B;A3BiqI/B;;A2B/tIA;EAgEM,cAAc;A3BmqIpB;;A2BnuIA;EAkEQ,gBAAgB;E1BuDpB,oB0BtD2C;A3BqqI/C;;A2BxuIA;EAqEQ,YAAY;EACZ,cAAc;A3BuqItB;;A2B7uIA;EAwEM,uBAAuB;A3ByqI7B;;A2BjvIA;EA0EM,yBAAyB;A3B2qI/B;;A2BrvIA;EA4EM,eAAe;A3B6qIrB;;A2BzvIA;EAgFU,sBAAsB;A3B6qIhC;;A2B7vIA;EAkFQ,uBAAuB;A3B+qI/B;;A2BjwIA;EAoFQ,gBAAgB;A3BirIxB;;ACrsIE;E0BhEF;IAuFM,aAAa;E3BmrIjB;AACF;;A2BlrIA;EAEI,kBAAkB;A3BorItB;;ACntIE;E0B6BF;IAII,qBAAqB;E3BurIvB;AACF;;ACrtIE;E0ByBF;IAMI,aAAa;IACb,YAAY;IACZ,cAAc;I1BwBd,mB0BvBsC;IACtC,iBAAiB;E3B2rInB;E2BrsIF;IAYM,kB5BhGU;I4BiGV,oBAAoB;E3B4rIxB;E2BzsIF;IAeM,oBAAoB;E3B6rIxB;E2B5sIF;IAiBM,kB5BvGU;I4BwGV,oBAAoB;E3B8rIxB;E2BhtIF;IAoBM,iB5B3GS;I4B4GT,oBAAoB;E3B+rIxB;AACF;;A2B9rIA;EAEI,gBAAgB;A3BgsIpB;;AClvIE;E0BgDF;IAII,aAAa;IACb,aAAa;IACb,YAAY;IACZ,cAAc;E3BmsIhB;E2B1sIF;IASM,gBAAgB;E3BosIpB;E2B7sIF;IAWM,cAAc;E3BqsIlB;E2BhtIF;IAaQ,YAAY;E3BssIlB;E2BntIF;I1BSI,oB0BM2C;E3BusI7C;AACF;;A2BtsIA;EACE,sBAAsB;EACtB,WAAW;EACX,e5BhIW;E4BiIX,kBAAkB;EAClB,mBAAmB;A3BysIrB;;A2B9sIA;;;EAaU,c5BxKoB;AC+2I9B;;A2BptIA;;;EAeQ,kB5B3IQ;ACs1IhB;;A2B1tIA;;;EAiBQ,kB5B/IQ;AC81IhB;;A2BhuIA;;;EAmBQ,iB5BlJO;ACq2If;;A2BtuIA;EAqBM,c5B7KwB;E4B8KxB,a7BjLgB;E6BkLhB,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,Y7BrLgB;E6BsLhB,UAAU;A3BqtIhB;;A2BhvIA;;EA+BM,mB7B1LgB;AEg5ItB;;A2BrvIA;EAiCM,OAAO;A3BwtIb;;A2BzvIA;;EAqCM,oB7BhMgB;AEy5ItB;;A2B9vIA;EAuCM,QAAQ;A3B2tId;;A2BlwIA;EA2CM,6BAA6B;E1B3C/B,a0B4C+B;EAC7B,YAAY;EACZ,UAAU;A3B2tIhB;;A2BzwIA;EAgDM,kB5B5KU;ACy4IhB;;A2B7wIA;EAkDM,kB5BhLU;AC+4IhB;;A2BjxIA;EAoDM,iB5BnLS;ACo5If;;A4Bv7IA,qBAAA;ACWA;EAGE,e9BuBW;E8BtBX,mBAAmB;A7B86IrB;;A6Bl7IA;EAMI,mBAAmB;EACnB,c9BI8B;E8BH9B,aAAa;EACb,uBAAuB;EACvB,iBAduC;A7B87I3C;;A6B17IA;EAYM,c9BjBwB;ACm8I9B;;A6B97IA;EAcI,mBAAmB;EACnB,aAAa;A7Bo7IjB;;A6Bn8IA;E5B+II,gB4B9HoC;A7Bs7IxC;;A6Bv8IA;EAoBQ,c9BzBsB;E8B0BtB,eAAe;EACf,oBAAoB;A7Bu7I5B;;A6B78IA;EAwBM,c9B1BwB;E8B2BxB,iBAAiB;A7By7IvB;;A6Bl9IA;;EA4BI,uBAAuB;EACvB,aAAa;EACb,eAAe;EACf,2BAA2B;A7B27I/B;;A6B19IA;E5B+II,kB4B7GuC;A7B47I3C;;A6B99IA;E5B+II,mB4B3GuC;A7B87I3C;;A6Bl+IA;;EAyCM,uBAAuB;A7B87I7B;;A6Bv+IA;;EA6CM,yBAAyB;A7B+7I/B;;A6B5+IA;EAgDI,kB9BrBY;ACq9IhB;;A6Bh/IA;EAkDI,kB9BzBY;AC29IhB;;A6Bp/IA;EAoDI,iB9B5BW;ACg+If;;A6Bx/IA;EAwDM,iBAAiB;A7Bo8IvB;;A6B5/IA;EA2DM,iBAAiB;A7Bq8IvB;;A6BhgJA;EA8DM,iBAAiB;A7Bs8IvB;;A6BpgJA;EAiEM,iBAAiB;A7Bu8IvB;;A8B7/IA;EACE,uB/BR6B;E+BS7B,sBAnBmB;EAoBnB,0F/BvB2B;E+BwB3B,c/BnB4B;E+BoB5B,eAAe;EACf,kBAAkB;A9BggJpB;;A8B7/IE;EACE,+BA3BiB;EA4BjB,gCA5BiB;A9B4hJrB;;A8B//IE;EACE,kCA9BiB;EA+BjB,mCA/BiB;A9BiiJrB;;A8BhgJA;EAEE,6BAjCwC;EAkCxC,oBAAoB;EACpB,kD/BxC2B;E+ByC3B,aAAa;A9BkgJf;;A8BhgJA;EACE,mBAAmB;EACnB,c/BzC4B;E+B0C5B,aAAa;EACb,YAAY;EACZ,gB/BNe;E+BOf,qBA1CgC;A9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B;;AiCp0JA;EAgBQ,kBAlBsB;AjC00J9B;;AiCx0JA;EAkBI,8ClCnB0B;EkCoB1B,gBA1BgB;EA2BhB,iBA3BgB;AjCq1JpB;;AiC90JA;EAwBM,kBA9BsB;EA+BtB,mBA/BsB;AjCy1J5B;;AiCxzJA;;EAEE,gBAAgB;EAChB,YAAY;EACZ,cAAc;AjC2zJhB;;AiCzzJA;EhC8GI,iBgCtJgB;AjCq2JpB;;AiC1zJA;EhC2GI,kBgCtJgB;AjCy2JpB;;AiC3zJA;EACE,gBAAgB;EAChB,YAAY;EACZ,cAAc;EACd,mBAAmB;AjC8zJrB;;ACvxJE;EgC3CF;IAQI,gBAAgB;EjC+zJlB;AACF;;AkCt2JA;EACE,enCgBW;ACy1Jb;;AkC12JA;EAII,kBnCcY;AC41JhB;;AkC92JA;EAMI,kBnCUY;ACk2JhB;;AkCl3JA;EAQI,iBnCOW;ACu2Jf;;AkC52JA;EACE,iBArB0B;AlCo4J5B;;AkCh3JA;EAGI,kBnCmCc;EmClCd,cnC3B0B;EmC4B1B,cAAc;EACd,qBAzBiC;AlC04JrC;;AkCv3JA;EAQM,4BnCzBwB;EmC0BxB,cnCjCwB;ACo5J9B;;AkC53JA;EAYM,yBnCpB4B;EmCqB5B,WxBuCU;AV60JhB;;AkCj4JA;EjC4HI,+BFhJ0B;EmCqCxB,cAnC0B;EjC8I5B,qBiC7IkC;AlCw5JtC;;AkCn3JA;EACE,cnC3C4B;EmC4C5B,iBApC2B;EAqC3B,qBApC+B;EAqC/B,yBAAyB;AlCs3J3B;;AkC13JA;EAMI,eAtCoB;AlC85JxB;;AkC93JA;EAQI,kBAxCoB;AlCk6JxB;;AmC75JA;EAEE,4BpCZ4B;EoCa5B,kBpC2CU;EoC1CV,epCUW;ACq5Jb;;AmCn6JA;EAMI,mBAAmB;AnCi6JvB;;AmCv6JA;EAQI,mBAAmB;EACnB,0BAA0B;AnCm6J9B;;AmC56JA;EAYI,kBpCGY;ACi6JhB;;AmCh7JA;EAcI,kBpCDY;ACu6JhB;;AmCp7JA;EAgBI,iBpCJW;AC46Jf;;AmCx7JA;EAsCM,uBAH+C;AnCy5JrD;;AmC57JA;EAwCQ,uBpChDuB;EoCiDvB,cpC9DqB;ACs9J7B;;AmCj8JA;EA2CQ,mBpCnDuB;AC68J/B;;AmCr8JA;EAsCM,yBAH+C;AnCs6JrD;;AmCz8JA;EAwCQ,yBpC7DqB;EoC8DrB,YpCjDuB;ACs9J/B;;AmC98JA;EA2CQ,qBpChEqB;ACu+J7B;;AmCl9JA;EAsCM,yBAH+C;AnCm7JrD;;AmCt9JA;EAwCQ,4BpClDsB;EoCmDtB,yBzBgBa;AVk6JrB;;AmC39JA;EA2CQ,wBpCrDsB;ACy+J9B;;AmC/9JA;EAsCM,yBAH+C;AnCg8JrD;;AmCn+JA;EAwCQ,yBpCzDsB;EoC0DtB,WzBkBQ;AV66JhB;;AmCx+JA;EA2CQ,qBpC5DsB;AC6/J9B;;AmC5+JA;EAsCM,yBzB4B0C;AV86JhD;;AmCh/JA;EAwCQ,yBpC3C0B;EoC4C1B,WzBkBQ;AV07JhB;;AmCr/JA;EA2CQ,qBpC9C0B;EoC+C1B,czB+B6D;AV+6JrE;;AmC1/JA;EAsCM,yBzB4B0C;AV47JhD;;AmC9/JA;EAwCQ,yBpCzC0B;EoC0C1B,WzBkBQ;AVw8JhB;;AmCngKA;EA2CQ,qBpC5C0B;EoC6C1B,czB+B6D;AV67JrE;;AmCxgKA;EAsCM,yBzB4B0C;AV08JhD;;AmC5gKA;EAwCQ,yBpC1C0B;EoC2C1B,WzBkBQ;AVs9JhB;;AmCjhKA;EA2CQ,qBpC7C0B;EoC8C1B,czB+B6D;AV28JrE;;AmCthKA;EAsCM,yBzB4B0C;AVw9JhD;;AmC1hKA;EAwCQ,yBpC5C0B;EoC6C1B,WzBkBQ;AVo+JhB;;AmC/hKA;EA2CQ,qBpC/C0B;EoCgD1B,czB+B6D;AVy9JrE;;AmCpiKA;EAsCM,yBzB4B0C;AVs+JhD;;AmCxiKA;EAwCQ,yBpC7C0B;EoC8C1B,yBzBgBa;AVo/JrB;;AmC7iKA;EA2CQ,qBpChD0B;EoCiD1B,czB+B6D;AVu+JrE;;AmCljKA;EAsCM,yBzB4B0C;AVo/JhD;;AmCtjKA;EAwCQ,yBpCvCyB;EoCwCzB,WzBkBQ;AVggKhB;;AmC3jKA;EA2CQ,qBpC1CyB;EoC2CzB,czB+B6D;AVq/JrE;;AmClhKA;EACE,mBAAmB;EACnB,yBpChE4B;EoCiE5B,0BAAgE;EAChE,WzBSc;EyBRd,aAAa;EACb,gBpC/Be;EoCgCf,8BAA8B;EAC9B,iBAAiB;EACjB,mBAtEiC;EAuEjC,kBAAkB;AnCqhKpB;;AmC/hKA;EAYI,YAAY;EACZ,cAAc;ElCwEd,oBkCvEsC;AnCuhK1C;;AmCriKA;EAgBI,eAjEgC;EAkEhC,yBAAyB;EACzB,0BAA0B;AnCyhK9B;;AmCvhKA;EACE,qBpChF4B;EoCiF5B,kBpCtBU;EoCuBV,mBAAmB;EACnB,uBAjFmC;EAkFnC,cpCvF4B;EoCwF5B,qBAjFiC;AnC2mKnC;;AmChiKA;;EASI,uBpCnF2B;AC+mK/B;;AmCriKA;EAWI,6BAlFgD;AnCgnKpD;;AoChmKA;EAEE,mBAAmB;EACnB,aAAa;EACb,sBAAsB;EACtB,uBAAuB;EACvB,gBAAgB;EAChB,eAAe;EACf,WAxCU;ApC0oKZ;;AoC1mKA;EAWI,aAAa;ApCmmKjB;;AoCjmKA;EAEE,wCrC/C2B;ACkpK7B;;AoCjmKA;;EAEE,cA9CgC;EA+ChC,+BAA0D;EAC1D,cAAc;EACd,kBAAkB;EAClB,WAAW;ApComKb;;ACxkKE;EmClCF;;IASI,cAAc;IACd,8BAA0D;IAC1D,YAxDuB;EpC+pKzB;AACF;;AoCtmKA;EAEE,gBAAgB;EAChB,YAxD2B;EAyD3B,eAAe;EnC8Fb,UmCtJoB;EA0DtB,SAzDoB;EA0DpB,WA5D2B;ApCoqK7B;;AoCtmKA;EACE,aAAa;EACb,sBAAsB;EACtB,8BAAgD;EAChD,gBAAgB;EAChB,uBAAuB;ApCymKzB;;AoCvmKA;;EAEE,mBAAmB;EACnB,4BrCtE4B;EqCuE5B,aAAa;EACb,cAAc;EACd,2BAA2B;EAC3B,aApE4B;EAqE5B,kBAAkB;ApC0mKpB;;AoCxmKA;EACE,gCrCjF4B;EqCkF5B,2BrCtBgB;EqCuBhB,4BrCvBgB;ACkoKlB;;AoCzmKA;EACE,crC1F4B;EqC2F5B,YAAY;EACZ,cAAc;EACd,iBrChEa;EqCiEb,cA7E8B;ApCyrKhC;;AoC1mKA;EACE,8BrCjCgB;EqCkChB,+BrClCgB;EqCmChB,6BrC/F4B;AC4sK9B;;AoChnKA;EnCoDI,kBmC9CuC;ApC8mK3C;;AoC5mKA;EnChDE,iCAAiC;EmCkDjC,uBrCjG6B;EqCkG7B,YAAY;EACZ,cAAc;EACd,cAAc;EACd,aAtF4B;ApCqsK9B;;AqCzqKA;EACE,uBtC5C6B;EsC6C7B,mBAvDqB;EAwDrB,kBAAkB;EAClB,WAtDW;ArCkuKb;;AqChrKA;EASM,uBtCpDyB;EsCqDzB,ctClEuB;AC6uK7B;;AqCrrKA;;EAcU,ctCtEmB;ACkvK7B;;AqC1rKA;;;;EAoBY,yB3B+BqB;E2B9BrB,ctC7EiB;AC0vK7B;;AqClsKA;EAwBY,qBtChFiB;AC8vK7B;;AqCtsKA;EA0BQ,ctClFqB;ACkwK7B;;AC/qKE;EoC3BF;;;;IAgCY,ctCxFiB;EC0wK3B;EqCltKF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,ctC/Fe;ECuxK3B;EqC/tKF;;IA0Cc,qBtClGe;EC2xK3B;EqCnuKF;;;IA8CU,yB3BKuB;I2BJvB,ctCvGmB;ECiyK3B;EqCzuKF;IAmDc,uBtC9FiB;IsC+FjB,ctC5Ge;ECqyK3B;AACF;;AqC9uKA;EASM,yBtCjEuB;EsCkEvB,YtCrDyB;AC8xK/B;;AqCnvKA;;EAcU,YtCzDqB;ACmyK/B;;AqCxvKA;;;;EAoBY,uB3B+BqB;E2B9BrB,YtChEmB;AC2yK/B;;AqChwKA;EAwBY,mBtCnEmB;AC+yK/B;;AqCpwKA;EA0BQ,YtCrEuB;ACmzK/B;;AC7uKE;EoC3BF;;;;IAgCY,YtC3EmB;EC2zK7B;EqChxKF;;;;;;;;;;IAsCc,uB3BamB;I2BZnB,YtClFiB;ECw0K7B;EqC7xKF;;IA0Cc,mBtCrFiB;EC40K7B;EqCjyKF;;;IA8CU,uB3BKuB;I2BJvB,YtC1FqB;ECk1K7B;EqCvyKF;IAmDc,yBtC3Ge;IsC4Gf,YtC/FiB;ECs1K7B;AACF;;AqC5yKA;EASM,4BtCtDwB;EsCuDxB,yB3BYe;AV2xKrB;;AqCjzKA;;EAcU,yB3BQW;AVgyKrB;;AqCtzKA;;;;EAoBY,yB3B+BqB;E2B9BrB,yB3BCS;AVwyKrB;;AqC9zKA;EAwBY,gC3BFS;AV4yKrB;;AqCl0KA;EA0BQ,yB3BJa;AVgzKrB;;AC3yKE;EoC3BF;;;;IAgCY,yB3BVS;EVwzKnB;EqC90KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,yB3BjBO;EVq0KnB;EqC31KF;;IA0Cc,gC3BpBO;EVy0KnB;EqC/1KF;;;IA8CU,yB3BKuB;I2BJvB,yB3BzBW;EV+0KnB;EqCr2KF;IAmDc,4BtChGgB;IsCiGhB,yB3B9BO;EVm1KnB;AACF;;AqC12KA;EASM,yBtC7DwB;EsC8DxB,W3BcU;AVu1KhB;;AqC/2KA;;EAcU,W3BUM;AV41KhB;;AqCp3KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVo2KhB;;AqC53KA;EAwBY,kB3BAI;AVw2KhB;;AqCh4KA;EA0BQ,W3BFQ;AV42KhB;;ACz2KE;EoC3BF;;;;IAgCY,W3BRI;EVo3Kd;EqC54KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVi4Kd;EqCz5KF;;IA0Cc,kB3BlBE;EVq4Kd;EqC75KF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EV24Kd;EqCn6KF;IAmDc,yBtCvGgB;IsCwGhB,W3B5BE;EV+4Kd;AACF;;AqCx6KA;EASM,yBtC/C4B;EsCgD5B,W3BcU;AVq5KhB;;AqC76KA;;EAcU,W3BUM;AV05KhB;;AqCl7KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVk6KhB;;AqC17KA;EAwBY,kB3BAI;AVs6KhB;;AqC97KA;EA0BQ,W3BFQ;AV06KhB;;ACv6KE;EoC3BF;;;;IAgCY,W3BRI;EVk7Kd;EqC18KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV+7Kd;EqCv9KF;;IA0Cc,kB3BlBE;EVm8Kd;EqC39KF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVy8Kd;EqCj+KF;IAmDc,yBtCzFoB;IsC0FpB,W3B5BE;EV68Kd;AACF;;AqCt+KA;EASM,yBtC7C4B;EsC8C5B,W3BcU;AVm9KhB;;AqC3+KA;;EAcU,W3BUM;AVw9KhB;;AqCh/KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVg+KhB;;AqCx/KA;EAwBY,kB3BAI;AVo+KhB;;AqC5/KA;EA0BQ,W3BFQ;AVw+KhB;;ACr+KE;EoC3BF;;;;IAgCY,W3BRI;EVg/Kd;EqCxgLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV6/Kd;EqCrhLF;;IA0Cc,kB3BlBE;EVigLd;EqCzhLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVugLd;EqC/hLF;IAmDc,yBtCvFoB;IsCwFpB,W3B5BE;EV2gLd;AACF;;AqCpiLA;EASM,yBtC9C4B;EsC+C5B,W3BcU;AVihLhB;;AqCziLA;;EAcU,W3BUM;AVshLhB;;AqC9iLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AV8hLhB;;AqCtjLA;EAwBY,kB3BAI;AVkiLhB;;AqC1jLA;EA0BQ,W3BFQ;AVsiLhB;;ACniLE;EoC3BF;;;;IAgCY,W3BRI;EV8iLd;EqCtkLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV2jLd;EqCnlLF;;IA0Cc,kB3BlBE;EV+jLd;EqCvlLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVqkLd;EqC7lLF;IAmDc,yBtCxFoB;IsCyFpB,W3B5BE;EVykLd;AACF;;AqClmLA;EASM,yBtChD4B;EsCiD5B,W3BcU;AV+kLhB;;AqCvmLA;;EAcU,W3BUM;AVolLhB;;AqC5mLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AV4lLhB;;AqCpnLA;EAwBY,kB3BAI;AVgmLhB;;AqCxnLA;EA0BQ,W3BFQ;AVomLhB;;ACjmLE;EoC3BF;;;;IAgCY,W3BRI;EV4mLd;EqCpoLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVynLd;EqCjpLF;;IA0Cc,kB3BlBE;EV6nLd;EqCrpLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVmoLd;EqC3pLF;IAmDc,yBtC1FoB;IsC2FpB,W3B5BE;EVuoLd;AACF;;AqChqLA;EASM,yBtCjD4B;EsCkD5B,yB3BYe;AV+oLrB;;AqCrqLA;;EAcU,yB3BQW;AVopLrB;;AqC1qLA;;;;EAoBY,yB3B+BqB;E2B9BrB,yB3BCS;AV4pLrB;;AqClrLA;EAwBY,gC3BFS;AVgqLrB;;AqCtrLA;EA0BQ,yB3BJa;AVoqLrB;;AC/pLE;EoC3BF;;;;IAgCY,yB3BVS;EV4qLnB;EqClsLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,yB3BjBO;EVyrLnB;EqC/sLF;;IA0Cc,gC3BpBO;EV6rLnB;EqCntLF;;;IA8CU,yB3BKuB;I2BJvB,yB3BzBW;EVmsLnB;EqCztLF;IAmDc,yBtC3FoB;IsC4FpB,yB3B9BO;EVusLnB;AACF;;AqC9tLA;EASM,yBtC3C2B;EsC4C3B,W3BcU;AV2sLhB;;AqCnuLA;;EAcU,W3BUM;AVgtLhB;;AqCxuLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVwtLhB;;AqChvLA;EAwBY,kB3BAI;AV4tLhB;;AqCpvLA;EA0BQ,W3BFQ;AVguLhB;;AC7tLE;EoC3BF;;;;IAgCY,W3BRI;EVwuLd;EqChwLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVqvLd;EqC7wLF;;IA0Cc,kB3BlBE;EVyvLd;EqCjxLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EV+vLd;EqCvxLF;IAmDc,yBtCrFmB;IsCsFnB,W3B5BE;EVmwLd;AACF;;AqC5xLA;EAsDI,oBAAoB;EACpB,aAAa;EACb,mBA7GmB;EA8GnB,WAAW;ArC0uLf;;AqCnyLA;EA2DI,gCtCxG0B;ACo1L9B;;AqCvyLA;EALE,OAAO;EACP,eAAe;EACf,QAAQ;EACR,WA/CiB;ArC+1LnB;;AqC9yLA;EAgEI,SAAS;ArCkvLb;;AqClzLA;EAkEM,iCtC/GwB;ACm2L9B;;AqCtzLA;EAoEI,MAAM;ArCsvLV;;AqCpvLA;;EAGI,oBA9HmB;ArCo3LvB;;AqCzvLA;;EAKI,uBAhImB;ArCy3LvB;;AqCvvLA;;EAEE,oBAAoB;EACpB,aAAa;EACb,cAAc;EACd,mBAvIqB;ArCi4LvB;;AqCxvLA;EAIM,6BAA6B;ArCwvLnC;;AqCtvLA;EpCtFE,iCAAiC;EoCwFjC,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;ArCyvLpB;;AqCvvLA;EAEE,ctCrJ4B;EEoB5B,eAAe;EACf,cAAc;EACd,eoCxBqB;EpCyBrB,kBAAkB;EAClB,coC1BqB;EpCqJnB,kBoCIkC;ArC6vLtC;;AC33LE;EACE,8BAA8B;EAC9B,cAAc;EACd,WAAW;EACX,qBAAqB;EACrB,kBAAkB;EAClB,wBAAwB;EACxB,yBFiCQ;EEhCR,yDAAyD;EACzD,oCF0Ba;EEzBb,WAAW;AD83Lf;;AC73LI;EACE,oBAAoB;ADg4L1B;;AC/3LI;EACE,oBAAoB;ADk4L1B;;ACj4LI;EACE,oBAAoB;ADo4L1B;;ACn4LE;EACE,qCAAiC;ADs4LrC;;ACl4LM;EACE,wCAAwC;ADq4LhD;;ACp4LM;EACE,UAAU;ADu4LlB;;ACt4LM;EACE,0CAA0C;ADy4LlD;;AqCpyLA;EACE,aAAa;ArCuyLf;;AqCryLA;;EAEE,ctC9J4B;EsC+J5B,cAAc;EACd,gBAAgB;EAChB,uBAAuB;EACvB,kBAAkB;ArCwyLpB;;AqC9yLA;;EASM,qBAAqB;EACrB,sBAAsB;ArC0yL5B;;AqCxyLA;;EAEE,eAAe;ArC2yLjB;;AqC7yLA;;;;;EAOI,yBtCxK0B;EsCyK1B,ctCjK8B;AC+8LlC;;AqC5yLA;EACE,YAAY;EACZ,cAAc;ArC+yLhB;;AqCjzLA;EAII,mBA7KgC;ArC89LpC;;AqCrzLA;EAMI,UAAU;ArCmzLd;;AqCzzLA;EAQI,YAAY;EACZ,cAAc;ArCqzLlB;;AqC9zLA;EAWI,oCAAoC;EACpC,mBAhMmB;EAiMnB,kCAAkC;ArCuzLtC;;AqCp0LA;EAgBM,6BArLyC;EAsLzC,4BtCpL4B;AC4+LlC;;AqCz0LA;EAmBM,6BArL0C;EAsL1C,4BtCvL4B;EsCwL5B,0BArLuC;EAsLvC,wBArLqC;EAsLrC,ctC1L4B;EsC2L5B,kCAAwE;ArC0zL9E;;AqCxzLA;EACE,YAAY;EACZ,cAAc;ArC2zLhB;;AqCzzLA;EpC7DI,mBoC8DoC;ArC4zLxC;;AqC7zLA;EAII,qBtCrM8B;EsCsM9B,oBAAoB;EpC1DpB,aoC2D6B;ArC6zLjC;;AqC3zLA;EACE,mBAAmB;EACnB,sBAAsB;EACtB,mBAAmB;ArC8zLrB;;AqCj0LA;EAKI,oBAAoB;EACpB,qBAAqB;ArCg0LzB;;AqC9zLA;EACE,4BtC3N4B;EsC4N5B,YAAY;EACZ,aAAa;EACb,WA/LyB;EAgMzB,gBAAgB;ArCi0LlB;;ACp9LE;EoC/BF;IAsLI,cAAc;ErCk0LhB;EqCj0LA;;IAGI,mBAAmB;IACnB,aAAa;ErCk0LjB;EqCj0LA;IAEI,aAAa;ErCk0LjB;EqC15LF;IA0FI,uBtC3O2B;IsC4O3B,4CtCzPyB;IsC0PzB,iBAAiB;ErCm0LnB;EqCt0LA;IAKI,cAAc;ErCo0LlB;EqCl0LA;IA3MA,OAAO;IACP,eAAe;IACf,QAAQ;IACR,WA/CiB;ErC+jMjB;EqCx0LA;IAKI,SAAS;ErCs0Lb;EqC30LA;IAOM,4CtCrQqB;EC4kM3B;EqC90LA;IASI,MAAM;ErCw0LV;EqCj1LA;IpClMA,iCAAiC;IoCgN3B,iCAA2C;IAC3C,cAAc;ErCu0LpB;EqCt0LA;;IAGI,oBA9QiB;ErCqlMrB;EqC10LA;;IAKI,uBAhRiB;ErCylMrB;AACF;;AC1gME;EoCmMA;;;;IAIE,oBAAoB;IACpB,aAAa;ErC20Lf;EqC9iMF;IAqOI,mBA1RmB;ErCsmMrB;EqC70LA;IAGI,kBA1R0B;ErCumM9B;EqCh1LA;;IAMM,mBAAmB;ErC80LzB;EqCp1LA;;IASM,kBtClOI;ECijMV;EqCx1LA;;;;IAgBQ,wCAAwC;ErC80LhD;EqC91LA;IAuBU,wCAAwC;ErC00LlD;EqCj2LA;IA4BU,4BtC7SkB;IsC8SlB,ctCzTiB;ECioM3B;EqCr2LA;IA+BU,4BtChTkB;IsCiTlB,ctCxSsB;ECinMhC;EqC7+LF;IAsKI,aAAa;ErC00Lf;EqCv+LF;;IAgKI,mBAAmB;IACnB,aAAa;ErC20Lf;EqCt9LF;IA8IM,oBAAoB;ErC20LxB;EqC70LA;IAKM,oDAAoD;ErC20L1D;EqCh1LA;IAOM,gCtClUsB;IsCmUtB,0BAAkE;IAClE,gBAAgB;IAChB,YAAY;IACZ,4CtC9UqB;IsC+UrB,SAAS;ErC40Lf;EqCx1LA;IAkBM,cAAc;ErCy0LpB;EqCx0LM;IAEE,UAAU;IACV,oBAAoB;IACpB,wBAAwB;ErCy0LhC;EqCrgMF;IA8LI,YAAY;IACZ,cAAc;ErC00LhB;EqCz0LA;IACE,2BAA2B;IpCvM3B,iBoCwMoC;ErC20LtC;EqC10LA;IACE,yBAAyB;IpC1MzB,kBoC2MoC;ErC40LtC;EqCl9LF;IAwII,uBtCxV2B;IsCyV3B,8BtClSc;IsCmSd,+BtCnSc;IsCoSd,6BtChW0B;IsCiW1B,2CtCzWyB;IsC0WzB,aAAa;IACb,mBAAmB;IpC3MnB,QoC4MuB;IACvB,eAAe;IACf,kBAAkB;IAClB,SAAS;IACT,WAjVkB;ErC8pMpB;EqCh+LF;IAqJM,sBAAsB;IACtB,mBAAmB;ErC80LvB;EqC71LA;IpC5ME,kBoC6NuC;ErC+0LzC;EqCh2LA;IAoBM,4BtC7WsB;IsC8WtB,ctCzXqB;ECwsM3B;EqCp2LA;IAuBM,4BtChXsB;IsCiXtB,ctCxW0B;ECwrMhC;EqC/0LE;IAEE,kBtC3TY;IsC4TZ,gBAAgB;IAChB,4EtCjYuB;IsCkYvB,cAAc;IACd,UAAU;IACV,oBAAoB;IACpB,wBAA8C;IAC9C,2BAA2B;IAC3B,yBtCjUM;IsCkUN,uCAAuC;ErCg1L3C;EqCp3LA;IAsCI,UAAU;IACV,QAAQ;ErCi1LZ;EqCv/LF;IAwKI,cAAc;ErCk1LhB;EqCj1LA;;IpCtPE,sBoCyPyC;ErCk1L3C;EqCr1LA;;IpCtPE,qBoC2PyC;ErCo1L3C;EqCl1LA;IAlWA,OAAO;IACP,eAAe;IACf,QAAQ;IACR,WA/CiB;ErCsuMjB;EqCx1LA;IAKI,SAAS;ErCs1Lb;EqC31LA;IAOM,4CtC5ZqB;ECmvM3B;EqC91LA;IASI,MAAM;ErCw1LV;EqCv1LA;;IAGI,oBA/ZiB;ErCuvMrB;EqC31LA;;IAKI,uBAjaiB;ErC2vMrB;EqC/1LA;;IAOI,oBAA4D;ErC41LhE;EqCn2LA;;IASI,uBAA+D;ErC81LnE;EqC51LA;;IAGI,ctC7auB;EC0wM3B;EqCh2LA;;IAKI,6BAla2C;ErCiwM/C;EqC91LA;IAKM,yBtCzasB;ECqwM5B;AACF;;AqCz1LA;EAEI,iCAA2C;ArC21L/C;;AsCnvMA;EAEE,evCFW;EuCGX,gBAnC0B;AtCwxM5B;;AsCxvMA;EAMI,kBvCLY;AC2vMhB;;AsC5vMA;EAQI,kBvCTY;ACiwMhB;;AsChwMA;EAUI,iBvCZW;ACswMf;;AsCpwMA;;EAcM,iBAAiB;EACjB,kBAAkB;EAClB,qBvCkBiB;ACyuMvB;;AsC3wMA;EAkBM,qBvCgBiB;AC6uMvB;;AsC3vMA;;EAEE,mBAAmB;EACnB,aAAa;EACb,uBAAuB;EACvB,kBAAkB;AtC8vMpB;;AsC5vMA;;;;EAME,cA9D6B;EA+D7B,uBAAuB;EACvB,eA/D8B;EAgE9B,mBA/DkC;EAgElC,oBA/DmC;EAgEnC,kBAAkB;AtC6vMpB;;AsC3vMA;;;EAGE,qBvCtE4B;EuCuE5B,cvC3E4B;EuC4E5B,gBxC3EoB;AEy0MtB;;AsCnwMA;;;EAOI,qBvC3E0B;EuC4E1B,cvC/E0B;ACi1M9B;;AsC1wMA;;;EAUI,qBvCjE8B;ACu0MlC;;AsChxMA;;;EAYI,iDvCvFyB;ACi2M7B;;AsCtxMA;;;EAcI,yBvCjF0B;EuCkF1B,qBvClF0B;EuCmF1B,gBAAgB;EAChB,cvCtF0B;EuCuF1B,YAAY;AtC8wMhB;;AsC5wMA;;EAEE,oBAtFkC;EAuFlC,qBAtFmC;EAuFnC,mBAAmB;AtC+wMrB;;AsC7wMA;EAEI,yBvCnF8B;EuCoF9B,qBvCpF8B;EuCqF9B,W5BzBY;AVwyMhB;;AsC7wMA;EACE,cvCrG4B;EuCsG5B,oBAAoB;AtCgxMtB;;AsC9wMA;EACE,eAAe;AtCixMjB;;AsClxMA;EAGI,gBAAgB;AtCmxMpB;;AC1yME;EqCxDF;IAmFI,eAAe;EtCoxMjB;EsC3yMF;;IA0BI,YAAY;IACZ,cAAc;EtCqxMhB;EsChyMF;IAcM,YAAY;IACZ,cAAc;EtCqxMlB;AACF;;ACrzME;EqCgBF;IAmBI,YAAY;IACZ,cAAc;IACd,2BAA2B;IAC3B,QAAQ;EtCuxMV;EsC91MF;;;;IA4EI,gBAAgB;IAChB,aAAa;EtCwxMf;EsCvxMA;IACE,QAAQ;EtCyxMV;EsCxxMA;IACE,QAAQ;EtC0xMV;EsCt4MF;IA8GI,8BAA8B;IAC9B,gBAAgB;IAChB,aAAa;EtC2xMf;EsC9xMA;IAMM,QAAQ;EtC2xMd;EsCjyMA;IAQM,uBAAuB;IACvB,QAAQ;EtC4xMd;EsCryMA;IAWM,QAAQ;EtC6xMd;EsCxyMA;IAcM,QAAQ;EtC6xMd;EsC3yMA;IAgBM,QAAQ;EtC8xMd;EsC9yMA;IAkBM,yBAAyB;IACzB,QAAQ;EtC+xMd;AACF;;AuCr6MA;EACE,kBxCqCgB;EwCpChB,0FxChC2B;EwCiC3B,exCEW;ACs6Mb;;AuC36MA;EAKI,qBxCWkB;AC+5MtB;;AuC/6MA;EAYQ,uBxC7BuB;EwC8BvB,cxC3CqB;ACk9M7B;;AuCp7MA;EAeQ,0BxChCuB;ACy8M/B;;AuCx7MA;EAiBQ,YxClCuB;AC68M/B;;AuC57MA;EAYQ,yBxC1CqB;EwC2CrB,YxC9BuB;ACk9M/B;;AuCj8MA;EAeQ,4BxC7CqB;ACm+M7B;;AuCr8MA;EAiBQ,cxC/CqB;ACu+M7B;;AuCz8MA;EAYQ,4BxC/BsB;EwCgCtB,yB7BmCa;AV85MrB;;AuC98MA;EAeQ,+BxClCsB;ACq+M9B;;AuCl9MA;EAiBQ,iBxCpCsB;ACy+M9B;;AuCt9MA;EAYQ,yBxCtCsB;EwCuCtB,W7BqCQ;AVy6MhB;;AuC39MA;EAeQ,4BxCzCsB;ACy/M9B;;AuC/9MA;EAiBQ,cxC3CsB;AC6/M9B;;AuCn+MA;EAYQ,yBxCxB0B;EwCyB1B,W7BqCQ;AVs7MhB;;AuCx+MA;EAeQ,4BxC3B0B;ACw/MlC;;AuC5+MA;EAiBQ,cxC7B0B;AC4/MlC;;AuCh/MA;EAYQ,yBxCtB0B;EwCuB1B,W7BqCQ;AVm8MhB;;AuCr/MA;EAeQ,4BxCzB0B;ACmgNlC;;AuCz/MA;EAiBQ,cxC3B0B;ACugNlC;;AuC7/MA;EAYQ,yBxCvB0B;EwCwB1B,W7BqCQ;AVg9MhB;;AuClgNA;EAeQ,4BxC1B0B;ACihNlC;;AuCtgNA;EAiBQ,cxC5B0B;ACqhNlC;;AuC1gNA;EAYQ,yBxCzB0B;EwC0B1B,W7BqCQ;AV69MhB;;AuC/gNA;EAeQ,4BxC5B0B;ACgiNlC;;AuCnhNA;EAiBQ,cxC9B0B;ACoiNlC;;AuCvhNA;EAYQ,yBxC1B0B;EwC2B1B,yB7BmCa;AV4+MrB;;AuC5hNA;EAeQ,4BxC7B0B;AC8iNlC;;AuChiNA;EAiBQ,cxC/B0B;ACkjNlC;;AuCpiNA;EAYQ,yBxCpByB;EwCqBzB,W7BqCQ;AVu/MhB;;AuCziNA;EAeQ,4BxCvByB;ACqjNjC;;AuC7iNA;EAiBQ,cxCzByB;ACyjNjC;;AuC9hNA;;EAGI,gCxC3C2B;AC2kN/B;;AuC9hNA;EACE,yBxC9C6B;EwC+C7B,0BAA8C;EAC9C,cxCrD4B;EwCsD5B,iBAhDyB;EAiDzB,gBxCjBe;EwCkBf,iBArD8B;EAsD9B,mBArDgC;AvCslNlC;;AuC/hNA;EACE,qBAAqB;EACrB,aAAa;EACb,kBArD4B;EAsD5B,uBAAuB;AvCkiNzB;;AuCtiNA;EAMI,gCxC7D0B;EwC8D1B,mBAAmB;EACnB,cAAc;AvCoiNlB;;AuC5iNA;EAWM,4BxCrEwB;EwCsExB,cxCvEwB;AC4mN9B;;AuCniNA;EAEI,cxC1E0B;AC+mN9B;;AuCviNA;EAIM,cxC7D4B;AComNlC;;AuCriNA;EACE,mBAAmB;EACnB,cxCjF4B;EwCkF5B,aAAa;EACb,2BAA2B;EAC3B,qBAAqB;AvCwiNvB;;AuC7iNA;EtCqEI,mBsC9DsC;AvC0iN1C;;AuCjjNA;EASI,YAAY;EACZ,cAAc;EACd,WAAW;AvC4iNf;;AuCvjNA;EAaI,eAAe;AvC8iNnB;;AuC3jNA;EAeI,0BxC9E8B;EwC+E9B,cxC/F0B;AC+oN9B;;AuChkNA;EAkBM,cxCjF4B;ACmoNlC;;AuCpkNA;EAoBI,8BxCnCc;EwCoCd,+BxCpCc;ACwlNlB;;AuCljNA;;EAEE,eAAe;AvCqjNjB;;AuCvjNA;;EAII,4BxCnG0B;AC2pN9B;;AuCtjNA;EtChGE,qBAAqB;EACrB,esCgGgB;EtC/FhB,WsC+FqB;EtC9FrB,gBsC8FqB;EtC7FrB,kBAAkB;EAClB,mBAAmB;EACnB,UsC2FqB;EACrB,cxC5G4B;EEkJ1B,mBsCrCoC;AvC+jNxC;;AuClkNA;EAKI,kBAAkB;EAClB,oBAAoB;AvCikNxB;;AwC3pNA;EvCgCE,iCAAiC;EuC5BjC,oBAAoB;EACpB,aAAa;EACb,ezCCW;EyCAX,8BAA8B;EAC9B,gBAAgB;EAChB,gBAAgB;EAChB,mBAAmB;AxC4pNrB;;AwCtqNA;EAYI,mBAAmB;EACnB,4BzCjC0B;EyCkC1B,0BAzC4B;EA0C5B,wBAzC0B;EA0C1B,czCvC0B;EyCwC1B,aAAa;EACb,uBAAuB;EACvB,mBAA6C;EAC7C,kBAxCyB;EAyCzB,mBAAmB;AxC8pNvB;;AwCnrNA;EAuBM,4BzC/CwB;EyCgDxB,czChDwB;ACgtN9B;;AwCxrNA;EA0BI,cAAc;AxCkqNlB;;AwC5rNA;EA6BQ,4BzCrC0B;EyCsC1B,czCtC0B;ACysNlC;;AwCjsNA;EAgCI,mBAAmB;EACnB,4BzCrD0B;EyCsD1B,0BA7D4B;EA8D5B,wBA7D0B;EA8D1B,aAAa;EACb,YAAY;EACZ,cAAc;EACd,2BAA2B;AxCqqN/B;;AwC5sNA;EAyCM,qBAAqB;AxCuqN3B;;AwChtNA;EA2CM,UAAU;EACV,uBAAuB;EACvB,oBAAoB;EACpB,qBAAqB;AxCyqN3B;;AwCvtNA;EAgDM,yBAAyB;EACzB,oBAAoB;AxC2qN1B;;AwC5tNA;EvC4HI,kBuCxEuC;AxC4qN3C;;AwChuNA;EvC4HI,mBuCtEuC;AxC8qN3C;;AwCpuNA;EA0DM,uBAAuB;AxC8qN7B;;AwCxuNA;EA6DM,yBAAyB;AxC+qN/B;;AwC5uNA;EAiEM,6BAA6B;EAI3B,0BzC9BI;AC0sNZ;;AwCjvNA;EAuEQ,4BzCxFsB;EyCyFtB,4BzC5FsB;AC0wN9B;;AwCtvNA;EA4EU,uBzC3FqB;EyC4FrB,qBzCjGoB;EyCkGpB,2CAA2E;AxC8qNrF;;AwC5vNA;EAiFM,YAAY;EACZ,cAAc;AxC+qNpB;;AwCjwNA;EAqFM,qBzCzGwB;EyC0GxB,mBA/F+B;EAgG/B,iBA/F6B;EAgG7B,gBAAgB;EAChB,kBAAkB;AxCgrNxB;;AwCzwNA;EA2FQ,4BzC5GsB;EyC6GtB,qBzCjHsB;EyCkHtB,UAAU;AxCkrNlB;;AwC/wNA;EvC4HI,kBuC5BuE;AxCmrN3E;;AwCnxNA;EAsGU,4BzC/DE;EyCgEF,+BzChEE;ACivNZ;;AwCxxNA;EA6GU,2BzCtEE;EyCuEF,8BzCvEE;ACsvNZ;;AwC7xNA;EAiHU,yBzCzHwB;EyC0HxB,qBzC1HwB;EyC2HxB,W9B/DM;E8BgEN,UAAU;AxCgrNpB;;AwCpyNA;EAsHM,mBAAmB;AxCkrNzB;;AwCxyNA;EA+HY,kCzCtFW;EyCuFX,+BzCvFW;EyCwFX,qBAAqB;AxC6qNjC;;AwC9yNA;EAwIY,iCzC/FW;EyCgGX,8BzChGW;EyCiGX,oBAAoB;AxC0qNhC;;AwCpzNA;EA6II,kBzCrIY;ACgzNhB;;AwCxzNA;EA+II,kBzCzIY;ACszNhB;;AwC5zNA;EAiJI,iBzC5IW;AC2zNf;;AyC91NA,eAAA;ACIA;EACE,cAAc;EACd,aAAa;EACb,YAAY;EACZ,cAAc;EACd,gBAPkB;A1Cq2NpB;;A0C71NE;EACE,UAAU;EACV,YAAY;A1Cg2NhB;;A0C/1NE;EACE,UAAU;EACV,WAAW;A1Ck2Nf;;A0Cj2NE;EACE,UAAU;EACV,UAAU;A1Co2Nd;;A0Cn2NE;EACE,UAAU;EACV,eAAe;A1Cs2NnB;;A0Cr2NE;EACE,UAAU;EACV,UAAU;A1Cw2Nd;;A0Cv2NE;EACE,UAAU;EACV,eAAe;A1C02NnB;;A0Cz2NE;EACE,UAAU;EACV,UAAU;A1C42Nd;;A0C32NE;EACE,UAAU;EACV,UAAU;A1C82Nd;;A0C72NE;EACE,UAAU;EACV,UAAU;A1Cg3Nd;;A0C/2NE;EACE,UAAU;EACV,UAAU;A1Ck3Nd;;A0Cj3NE;EACE,UAAU;EACV,UAAU;A1Co3Nd;;A0Cn3NE;EzC+GE,iByC9GmC;A1Cs3NvC;;A0Cr3NE;EzC6GE,sByC5GwC;A1Cw3N5C;;A0Cv3NE;EzC2GE,iByC1GmC;A1C03NvC;;A0Cz3NE;EzCyGE,sByCxGwC;A1C43N5C;;A0C33NE;EzCuGE,iByCtGmC;A1C83NvC;;A0C73NE;EzCqGE,iByCpGmC;A1Cg4NvC;;A0C/3NE;EzCmGE,iByClGmC;A1Ck4NvC;;A0Cj4NE;EzCiGE,iByChGmC;A1Co4NvC;;A0Cn4NE;EzC+FE,iByC9FmC;A1Cs4NvC;;A0Cp4NI;EACE,UAAU;EACV,SAAiC;A1Cu4NvC;;A0Ct4NI;EzCyFA,gByCxF4D;A1Cy4NhE;;A0C74NI;EACE,UAAU;EACV,eAAiC;A1Cg5NvC;;A0C/4NI;EzCyFA,sByCxF4D;A1Ck5NhE;;A0Ct5NI;EACE,UAAU;EACV,gBAAiC;A1Cy5NvC;;A0Cx5NI;EzCyFA,uByCxF4D;A1C25NhE;;A0C/5NI;EACE,UAAU;EACV,UAAiC;A1Ck6NvC;;A0Cj6NI;EzCyFA,iByCxF4D;A1Co6NhE;;A0Cx6NI;EACE,UAAU;EACV,gBAAiC;A1C26NvC;;A0C16NI;EzCyFA,uByCxF4D;A1C66NhE;;A0Cj7NI;EACE,UAAU;EACV,gBAAiC;A1Co7NvC;;A0Cn7NI;EzCyFA,uByCxF4D;A1Cs7NhE;;A0C17NI;EACE,UAAU;EACV,UAAiC;A1C67NvC;;A0C57NI;EzCyFA,iByCxF4D;A1C+7NhE;;A0Cn8NI;EACE,UAAU;EACV,gBAAiC;A1Cs8NvC;;A0Cr8NI;EzCyFA,uByCxF4D;A1Cw8NhE;;A0C58NI;EACE,UAAU;EACV,gBAAiC;A1C+8NvC;;A0C98NI;EzCyFA,uByCxF4D;A1Ci9NhE;;A0Cr9NI;EACE,UAAU;EACV,UAAiC;A1Cw9NvC;;A0Cv9NI;EzCyFA,iByCxF4D;A1C09NhE;;A0C99NI;EACE,UAAU;EACV,gBAAiC;A1Ci+NvC;;A0Ch+NI;EzCyFA,uByCxF4D;A1Cm+NhE;;A0Cv+NI;EACE,UAAU;EACV,gBAAiC;A1C0+NvC;;A0Cz+NI;EzCyFA,uByCxF4D;A1C4+NhE;;A0Ch/NI;EACE,UAAU;EACV,WAAiC;A1Cm/NvC;;A0Cl/NI;EzCyFA,kByCxF4D;A1Cq/NhE;;AC19NE;EyCzFF;IAiEM,UAAU;IACV,YAAY;E1Cu/NhB;E0CzjOF;IAoEM,UAAU;IACV,WAAW;E1Cw/Nf;E0C7jOF;IAuEM,UAAU;IACV,UAAU;E1Cy/Nd;E0CjkOF;IA0EM,UAAU;IACV,eAAe;E1C0/NnB;E0CrkOF;IA6EM,UAAU;IACV,UAAU;E1C2/Nd;E0CzkOF;IAgFM,UAAU;IACV,eAAe;E1C4/NnB;E0C7kOF;IAmFM,UAAU;IACV,UAAU;E1C6/Nd;E0CjlOF;IAsFM,UAAU;IACV,UAAU;E1C8/Nd;E0CrlOF;IAyFM,UAAU;IACV,UAAU;E1C+/Nd;E0CzlOF;IA4FM,UAAU;IACV,UAAU;E1CggOd;E0C7lOF;IA+FM,UAAU;IACV,UAAU;E1CigOd;E0CjmOF;IzCsJI,iByCpDqC;E1CkgOvC;E0CpmOF;IzCsJI,sByClD0C;E1CmgO5C;E0CvmOF;IzCsJI,iByChDqC;E1CogOvC;E0C1mOF;IzCsJI,sByC9C0C;E1CqgO5C;E0C7mOF;IzCsJI,iByC5CqC;E1CsgOvC;E0ChnOF;IzCsJI,iByC1CqC;E1CugOvC;E0CnnOF;IzCsJI,iByCxCqC;E1CwgOvC;E0CtnOF;IzCsJI,iByCtCqC;E1CygOvC;E0CznOF;IzCsJI,iByCpCqC;E1C0gOvC;E0C5nOF;IAqHQ,UAAU;IACV,SAAiC;E1C0gOvC;E0ChoOF;IzCsJI,gByC9B8D;E1C2gOhE;E0CnoOF;IAqHQ,UAAU;IACV,eAAiC;E1CihOvC;E0CvoOF;IzCsJI,sByC9B8D;E1CkhOhE;E0C1oOF;IAqHQ,UAAU;IACV,gBAAiC;E1CwhOvC;E0C9oOF;IzCsJI,uByC9B8D;E1CyhOhE;E0CjpOF;IAqHQ,UAAU;IACV,UAAiC;E1C+hOvC;E0CrpOF;IzCsJI,iByC9B8D;E1CgiOhE;E0CxpOF;IAqHQ,UAAU;IACV,gBAAiC;E1CsiOvC;E0C5pOF;IzCsJI,uByC9B8D;E1CuiOhE;E0C/pOF;IAqHQ,UAAU;IACV,gBAAiC;E1C6iOvC;E0CnqOF;IzCsJI,uByC9B8D;E1C8iOhE;E0CtqOF;IAqHQ,UAAU;IACV,UAAiC;E1CojOvC;E0C1qOF;IzCsJI,iByC9B8D;E1CqjOhE;E0C7qOF;IAqHQ,UAAU;IACV,gBAAiC;E1C2jOvC;E0CjrOF;IzCsJI,uByC9B8D;E1C4jOhE;E0CprOF;IAqHQ,UAAU;IACV,gBAAiC;E1CkkOvC;E0CxrOF;IzCsJI,uByC9B8D;E1CmkOhE;E0C3rOF;IAqHQ,UAAU;IACV,UAAiC;E1CykOvC;E0C/rOF;IzCsJI,iByC9B8D;E1C0kOhE;E0ClsOF;IAqHQ,UAAU;IACV,gBAAiC;E1CglOvC;E0CtsOF;IzCsJI,uByC9B8D;E1CilOhE;E0CzsOF;IAqHQ,UAAU;IACV,gBAAiC;E1CulOvC;E0C7sOF;IzCsJI,uByC9B8D;E1CwlOhE;E0ChtOF;IAqHQ,UAAU;IACV,WAAiC;E1C8lOvC;E0CptOF;IzCsJI,kByC9B8D;E1C+lOhE;AACF;;AC3nOE;EyC7FF;IA4HM,UAAU;IACV,YAAY;E1CimOhB;E0C9tOF;IAgIM,UAAU;IACV,WAAW;E1CimOf;E0CluOF;IAoIM,UAAU;IACV,UAAU;E1CimOd;E0CtuOF;IAwIM,UAAU;IACV,eAAe;E1CimOnB;E0C1uOF;IA4IM,UAAU;IACV,UAAU;E1CimOd;E0C9uOF;IAgJM,UAAU;IACV,eAAe;E1CimOnB;E0ClvOF;IAoJM,UAAU;IACV,UAAU;E1CimOd;E0CtvOF;IAwJM,UAAU;IACV,UAAU;E1CimOd;E0C1vOF;IA4JM,UAAU;IACV,UAAU;E1CimOd;E0C9vOF;IAgKM,UAAU;IACV,UAAU;E1CimOd;E0ClwOF;IAoKM,UAAU;IACV,UAAU;E1CimOd;E0CtwOF;IzCsJI,iByCkBqC;E1CimOvC;E0CzwOF;IzCsJI,sByCqB0C;E1CimO5C;E0C5wOF;IzCsJI,iByCwBqC;E1CimOvC;E0C/wOF;IzCsJI,sByC2B0C;E1CimO5C;E0ClxOF;IzCsJI,iByC8BqC;E1CimOvC;E0CrxOF;IzCsJI,iByCiCqC;E1CimOvC;E0CxxOF;IzCsJI,iByCoCqC;E1CimOvC;E0C3xOF;IzCsJI,iByCuCqC;E1CimOvC;E0C9xOF;IzCsJI,iByC0CqC;E1CimOvC;E0CjyOF;IAoMQ,UAAU;IACV,SAAiC;E1CgmOvC;E0CryOF;IzCsJI,gByCkD8D;E1CgmOhE;E0CxyOF;IAoMQ,UAAU;IACV,eAAiC;E1CumOvC;E0C5yOF;IzCsJI,sByCkD8D;E1CumOhE;E0C/yOF;IAoMQ,UAAU;IACV,gBAAiC;E1C8mOvC;E0CnzOF;IzCsJI,uByCkD8D;E1C8mOhE;E0CtzOF;IAoMQ,UAAU;IACV,UAAiC;E1CqnOvC;E0C1zOF;IzCsJI,iByCkD8D;E1CqnOhE;E0C7zOF;IAoMQ,UAAU;IACV,gBAAiC;E1C4nOvC;E0Cj0OF;IzCsJI,uByCkD8D;E1C4nOhE;E0Cp0OF;IAoMQ,UAAU;IACV,gBAAiC;E1CmoOvC;E0Cx0OF;IzCsJI,uByCkD8D;E1CmoOhE;E0C30OF;IAoMQ,UAAU;IACV,UAAiC;E1C0oOvC;E0C/0OF;IzCsJI,iByCkD8D;E1C0oOhE;E0Cl1OF;IAoMQ,UAAU;IACV,gBAAiC;E1CipOvC;E0Ct1OF;IzCsJI,uByCkD8D;E1CipOhE;E0Cz1OF;IAoMQ,UAAU;IACV,gBAAiC;E1CwpOvC;E0C71OF;IzCsJI,uByCkD8D;E1CwpOhE;E0Ch2OF;IAoMQ,UAAU;IACV,UAAiC;E1C+pOvC;E0Cp2OF;IzCsJI,iByCkD8D;E1C+pOhE;E0Cv2OF;IAoMQ,UAAU;IACV,gBAAiC;E1CsqOvC;E0C32OF;IzCsJI,uByCkD8D;E1CsqOhE;E0C92OF;IAoMQ,UAAU;IACV,gBAAiC;E1C6qOvC;E0Cl3OF;IzCsJI,uByCkD8D;E1C6qOhE;E0Cr3OF;IAoMQ,UAAU;IACV,WAAiC;E1CorOvC;E0Cz3OF;IzCsJI,kByCkD8D;E1CorOhE;AACF;;ACxxOE;EyCrGF;IA2MM,UAAU;IACV,YAAY;E1CurOhB;E0Cn4OF;IA8MM,UAAU;IACV,WAAW;E1CwrOf;E0Cv4OF;IAiNM,UAAU;IACV,UAAU;E1CyrOd;E0C34OF;IAoNM,UAAU;IACV,eAAe;E1C0rOnB;E0C/4OF;IAuNM,UAAU;IACV,UAAU;E1C2rOd;E0Cn5OF;IA0NM,UAAU;IACV,eAAe;E1C4rOnB;E0Cv5OF;IA6NM,UAAU;IACV,UAAU;E1C6rOd;E0C35OF;IAgOM,UAAU;IACV,UAAU;E1C8rOd;E0C/5OF;IAmOM,UAAU;IACV,UAAU;E1C+rOd;E0Cn6OF;IAsOM,UAAU;IACV,UAAU;E1CgsOd;E0Cv6OF;IAyOM,UAAU;IACV,UAAU;E1CisOd;E0C36OF;IzCsJI,iByCsFqC;E1CksOvC;E0C96OF;IzCsJI,sByCwF0C;E1CmsO5C;E0Cj7OF;IzCsJI,iByC0FqC;E1CosOvC;E0Cp7OF;IzCsJI,sByC4F0C;E1CqsO5C;E0Cv7OF;IzCsJI,iByC8FqC;E1CssOvC;E0C17OF;IzCsJI,iByCgGqC;E1CusOvC;E0C77OF;IzCsJI,iByCkGqC;E1CwsOvC;E0Ch8OF;IzCsJI,iByCoGqC;E1CysOvC;E0Cn8OF;IzCsJI,iByCsGqC;E1C0sOvC;E0Ct8OF;IA+PQ,UAAU;IACV,SAAiC;E1C0sOvC;E0C18OF;IzCsJI,gByC4G8D;E1C2sOhE;E0C78OF;IA+PQ,UAAU;IACV,eAAiC;E1CitOvC;E0Cj9OF;IzCsJI,sByC4G8D;E1CktOhE;E0Cp9OF;IA+PQ,UAAU;IACV,gBAAiC;E1CwtOvC;E0Cx9OF;IzCsJI,uByC4G8D;E1CytOhE;E0C39OF;IA+PQ,UAAU;IACV,UAAiC;E1C+tOvC;E0C/9OF;IzCsJI,iByC4G8D;E1CguOhE;E0Cl+OF;IA+PQ,UAAU;IACV,gBAAiC;E1CsuOvC;E0Ct+OF;IzCsJI,uByC4G8D;E1CuuOhE;E0Cz+OF;IA+PQ,UAAU;IACV,gBAAiC;E1C6uOvC;E0C7+OF;IzCsJI,uByC4G8D;E1C8uOhE;E0Ch/OF;IA+PQ,UAAU;IACV,UAAiC;E1CovOvC;E0Cp/OF;IzCsJI,iByC4G8D;E1CqvOhE;E0Cv/OF;IA+PQ,UAAU;IACV,gBAAiC;E1C2vOvC;E0C3/OF;IzCsJI,uByC4G8D;E1C4vOhE;E0C9/OF;IA+PQ,UAAU;IACV,gBAAiC;E1CkwOvC;E0ClgPF;IzCsJI,uByC4G8D;E1CmwOhE;E0CrgPF;IA+PQ,UAAU;IACV,UAAiC;E1CywOvC;E0CzgPF;IzCsJI,iByC4G8D;E1C0wOhE;E0C5gPF;IA+PQ,UAAU;IACV,gBAAiC;E1CgxOvC;E0ChhPF;IzCsJI,uByC4G8D;E1CixOhE;E0CnhPF;IA+PQ,UAAU;IACV,gBAAiC;E1CuxOvC;E0CvhPF;IzCsJI,uByC4G8D;E1CwxOhE;E0C1hPF;IA+PQ,UAAU;IACV,WAAiC;E1C8xOvC;E0C9hPF;IzCsJI,kByC4G8D;E1C+xOhE;AACF;;ACz7OE;EyCzGF;IAqQM,UAAU;IACV,YAAY;E1CkyOhB;E0CxiPF;IAwQM,UAAU;IACV,WAAW;E1CmyOf;E0C5iPF;IA2QM,UAAU;IACV,UAAU;E1CoyOd;E0ChjPF;IA8QM,UAAU;IACV,eAAe;E1CqyOnB;E0CpjPF;IAiRM,UAAU;IACV,UAAU;E1CsyOd;E0CxjPF;IAoRM,UAAU;IACV,eAAe;E1CuyOnB;E0C5jPF;IAuRM,UAAU;IACV,UAAU;E1CwyOd;E0ChkPF;IA0RM,UAAU;IACV,UAAU;E1CyyOd;E0CpkPF;IA6RM,UAAU;IACV,UAAU;E1C0yOd;E0CxkPF;IAgSM,UAAU;IACV,UAAU;E1C2yOd;E0C5kPF;IAmSM,UAAU;IACV,UAAU;E1C4yOd;E0ChlPF;IzCsJI,iByCgJqC;E1C6yOvC;E0CnlPF;IzCsJI,sByCkJ0C;E1C8yO5C;E0CtlPF;IzCsJI,iByCoJqC;E1C+yOvC;E0CzlPF;IzCsJI,sByCsJ0C;E1CgzO5C;E0C5lPF;IzCsJI,iByCwJqC;E1CizOvC;E0C/lPF;IzCsJI,iByC0JqC;E1CkzOvC;E0ClmPF;IzCsJI,iByC4JqC;E1CmzOvC;E0CrmPF;IzCsJI,iByC8JqC;E1CozOvC;E0CxmPF;IzCsJI,iByCgKqC;E1CqzOvC;E0C3mPF;IAyTQ,UAAU;IACV,SAAiC;E1CqzOvC;E0C/mPF;IzCsJI,gByCsK8D;E1CszOhE;E0ClnPF;IAyTQ,UAAU;IACV,eAAiC;E1C4zOvC;E0CtnPF;IzCsJI,sByCsK8D;E1C6zOhE;E0CznPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cm0OvC;E0C7nPF;IzCsJI,uByCsK8D;E1Co0OhE;E0ChoPF;IAyTQ,UAAU;IACV,UAAiC;E1C00OvC;E0CpoPF;IzCsJI,iByCsK8D;E1C20OhE;E0CvoPF;IAyTQ,UAAU;IACV,gBAAiC;E1Ci1OvC;E0C3oPF;IzCsJI,uByCsK8D;E1Ck1OhE;E0C9oPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cw1OvC;E0ClpPF;IzCsJI,uByCsK8D;E1Cy1OhE;E0CrpPF;IAyTQ,UAAU;IACV,UAAiC;E1C+1OvC;E0CzpPF;IzCsJI,iByCsK8D;E1Cg2OhE;E0C5pPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cs2OvC;E0ChqPF;IzCsJI,uByCsK8D;E1Cu2OhE;E0CnqPF;IAyTQ,UAAU;IACV,gBAAiC;E1C62OvC;E0CvqPF;IzCsJI,uByCsK8D;E1C82OhE;E0C1qPF;IAyTQ,UAAU;IACV,UAAiC;E1Co3OvC;E0C9qPF;IzCsJI,iByCsK8D;E1Cq3OhE;E0CjrPF;IAyTQ,UAAU;IACV,gBAAiC;E1C23OvC;E0CrrPF;IzCsJI,uByCsK8D;E1C43OhE;E0CxrPF;IAyTQ,UAAU;IACV,gBAAiC;E1Ck4OvC;E0C5rPF;IzCsJI,uByCsK8D;E1Cm4OhE;E0C/rPF;IAyTQ,UAAU;IACV,WAAiC;E1Cy4OvC;E0CnsPF;IzCsJI,kByCsK8D;E1C04OhE;AACF;;AC/kPI;EyCxHJ;IA+TM,UAAU;IACV,YAAY;E1C64OhB;E0C7sPF;IAkUM,UAAU;IACV,WAAW;E1C84Of;E0CjtPF;IAqUM,UAAU;IACV,UAAU;E1C+4Od;E0CrtPF;IAwUM,UAAU;IACV,eAAe;E1Cg5OnB;E0CztPF;IA2UM,UAAU;IACV,UAAU;E1Ci5Od;E0C7tPF;IA8UM,UAAU;IACV,eAAe;E1Ck5OnB;E0CjuPF;IAiVM,UAAU;IACV,UAAU;E1Cm5Od;E0CruPF;IAoVM,UAAU;IACV,UAAU;E1Co5Od;E0CzuPF;IAuVM,UAAU;IACV,UAAU;E1Cq5Od;E0C7uPF;IA0VM,UAAU;IACV,UAAU;E1Cs5Od;E0CjvPF;IA6VM,UAAU;IACV,UAAU;E1Cu5Od;E0CrvPF;IzCsJI,iByC0MqC;E1Cw5OvC;E0CxvPF;IzCsJI,sByC4M0C;E1Cy5O5C;E0C3vPF;IzCsJI,iByC8MqC;E1C05OvC;E0C9vPF;IzCsJI,sByCgN0C;E1C25O5C;E0CjwPF;IzCsJI,iByCkNqC;E1C45OvC;E0CpwPF;IzCsJI,iByCoNqC;E1C65OvC;E0CvwPF;IzCsJI,iByCsNqC;E1C85OvC;E0C1wPF;IzCsJI,iByCwNqC;E1C+5OvC;E0C7wPF;IzCsJI,iByC0NqC;E1Cg6OvC;E0ChxPF;IAmXQ,UAAU;IACV,SAAiC;E1Cg6OvC;E0CpxPF;IzCsJI,gByCgO8D;E1Ci6OhE;E0CvxPF;IAmXQ,UAAU;IACV,eAAiC;E1Cu6OvC;E0C3xPF;IzCsJI,sByCgO8D;E1Cw6OhE;E0C9xPF;IAmXQ,UAAU;IACV,gBAAiC;E1C86OvC;E0ClyPF;IzCsJI,uByCgO8D;E1C+6OhE;E0CryPF;IAmXQ,UAAU;IACV,UAAiC;E1Cq7OvC;E0CzyPF;IzCsJI,iByCgO8D;E1Cs7OhE;E0C5yPF;IAmXQ,UAAU;IACV,gBAAiC;E1C47OvC;E0ChzPF;IzCsJI,uByCgO8D;E1C67OhE;E0CnzPF;IAmXQ,UAAU;IACV,gBAAiC;E1Cm8OvC;E0CvzPF;IzCsJI,uByCgO8D;E1Co8OhE;E0C1zPF;IAmXQ,UAAU;IACV,UAAiC;E1C08OvC;E0C9zPF;IzCsJI,iByCgO8D;E1C28OhE;E0Cj0PF;IAmXQ,UAAU;IACV,gBAAiC;E1Ci9OvC;E0Cr0PF;IzCsJI,uByCgO8D;E1Ck9OhE;E0Cx0PF;IAmXQ,UAAU;IACV,gBAAiC;E1Cw9OvC;E0C50PF;IzCsJI,uByCgO8D;E1Cy9OhE;E0C/0PF;IAmXQ,UAAU;IACV,UAAiC;E1C+9OvC;E0Cn1PF;IzCsJI,iByCgO8D;E1Cg+OhE;E0Ct1PF;IAmXQ,UAAU;IACV,gBAAiC;E1Cs+OvC;E0C11PF;IzCsJI,uByCgO8D;E1Cu+OhE;E0C71PF;IAmXQ,UAAU;IACV,gBAAiC;E1C6+OvC;E0Cj2PF;IzCsJI,uByCgO8D;E1C8+OhE;E0Cp2PF;IAmXQ,UAAU;IACV,WAAiC;E1Co/OvC;E0Cx2PF;IzCsJI,kByCgO8D;E1Cq/OhE;AACF;;ACruPI;EyCvIJ;IAyXM,UAAU;IACV,YAAY;E1Cw/OhB;E0Cl3PF;IA4XM,UAAU;IACV,WAAW;E1Cy/Of;E0Ct3PF;IA+XM,UAAU;IACV,UAAU;E1C0/Od;E0C13PF;IAkYM,UAAU;IACV,eAAe;E1C2/OnB;E0C93PF;IAqYM,UAAU;IACV,UAAU;E1C4/Od;E0Cl4PF;IAwYM,UAAU;IACV,eAAe;E1C6/OnB;E0Ct4PF;IA2YM,UAAU;IACV,UAAU;E1C8/Od;E0C14PF;IA8YM,UAAU;IACV,UAAU;E1C+/Od;E0C94PF;IAiZM,UAAU;IACV,UAAU;E1CggPd;E0Cl5PF;IAoZM,UAAU;IACV,UAAU;E1CigPd;E0Ct5PF;IAuZM,UAAU;IACV,UAAU;E1CkgPd;E0C15PF;IzCsJI,iByCoQqC;E1CmgPvC;E0C75PF;IzCsJI,sByCsQ0C;E1CogP5C;E0Ch6PF;IzCsJI,iByCwQqC;E1CqgPvC;E0Cn6PF;IzCsJI,sByC0Q0C;E1CsgP5C;E0Ct6PF;IzCsJI,iByC4QqC;E1CugPvC;E0Cz6PF;IzCsJI,iByC8QqC;E1CwgPvC;E0C56PF;IzCsJI,iByCgRqC;E1CygPvC;E0C/6PF;IzCsJI,iByCkRqC;E1C0gPvC;E0Cl7PF;IzCsJI,iByCoRqC;E1C2gPvC;E0Cr7PF;IA6aQ,UAAU;IACV,SAAiC;E1C2gPvC;E0Cz7PF;IzCsJI,gByC0R8D;E1C4gPhE;E0C57PF;IA6aQ,UAAU;IACV,eAAiC;E1CkhPvC;E0Ch8PF;IzCsJI,sByC0R8D;E1CmhPhE;E0Cn8PF;IA6aQ,UAAU;IACV,gBAAiC;E1CyhPvC;E0Cv8PF;IzCsJI,uByC0R8D;E1C0hPhE;E0C18PF;IA6aQ,UAAU;IACV,UAAiC;E1CgiPvC;E0C98PF;IzCsJI,iByC0R8D;E1CiiPhE;E0Cj9PF;IA6aQ,UAAU;IACV,gBAAiC;E1CuiPvC;E0Cr9PF;IzCsJI,uByC0R8D;E1CwiPhE;E0Cx9PF;IA6aQ,UAAU;IACV,gBAAiC;E1C8iPvC;E0C59PF;IzCsJI,uByC0R8D;E1C+iPhE;E0C/9PF;IA6aQ,UAAU;IACV,UAAiC;E1CqjPvC;E0Cn+PF;IzCsJI,iByC0R8D;E1CsjPhE;E0Ct+PF;IA6aQ,UAAU;IACV,gBAAiC;E1C4jPvC;E0C1+PF;IzCsJI,uByC0R8D;E1C6jPhE;E0C7+PF;IA6aQ,UAAU;IACV,gBAAiC;E1CmkPvC;E0Cj/PF;IzCsJI,uByC0R8D;E1CokPhE;E0Cp/PF;IA6aQ,UAAU;IACV,UAAiC;E1C0kPvC;E0Cx/PF;IzCsJI,iByC0R8D;E1C2kPhE;E0C3/PF;IA6aQ,UAAU;IACV,gBAAiC;E1CilPvC;E0C//PF;IzCsJI,uByC0R8D;E1CklPhE;E0ClgQF;IA6aQ,UAAU;IACV,gBAAiC;E1CwlPvC;E0CtgQF;IzCsJI,uByC0R8D;E1CylPhE;E0CzgQF;IA6aQ,UAAU;IACV,WAAiC;E1C+lPvC;E0C7gQF;IzCsJI,kByC0R8D;E1CgmPhE;AACF;;A0C/lPA;EzC5RI,sByCxJgB;EzCwJhB,qByCxJgB;EAublB,oBAvbkB;A1CyhQpB;;A0CrmPA;EAKI,uBAzbgB;A1C6hQpB;;A0CzmPA;EAOI,qCAA4C;A1CsmPhD;;A0C7mPA;EAUI,uBAAuB;A1CumP3B;;A0CjnPA;EzC5RI,eyCwSiC;EzCxSjC,cyCySiC;EACjC,aAAa;A1CymPjB;;A0CvnPA;EAgBM,SAAS;EACT,qBAAqB;A1C2mP3B;;A0C5nPA;EAmBM,qBAAqB;A1C6mP3B;;A0ChoPA;EAqBM,gBAAgB;A1C+mPtB;;A0CpoPA;EAuBI,aAAa;A1CinPjB;;A0CxoPA;EAyBI,eAAe;A1CmnPnB;;A0C5oPA;EA2BI,mBAAmB;A1CqnPvB;;ACr+PE;EyCqVF;IA+BM,aAAa;E1CsnPjB;AACF;;AC/9PE;EyCyUF;IAmCM,aAAa;E1CwnPjB;AACF;;A0CtnPE;EACE,oBAAY;EzCnUZ,yCyCoU2D;EzCpU3D,wCyCqU2D;A1CynP/D;;A0C5nPE;EAKI,8BAA8B;EAC9B,+BAA+B;A1C2nPrC;;A0CjoPE;EASM,iBAAY;A1C4nPpB;;ACpgQE;EyC+XA;IAYQ,iBAAY;E1C8nPpB;AACF;;ACtgQE;EyC2XA;IAeQ,iBAAY;E1CioPpB;AACF;;ACxgQE;EyCuXA;IAkBQ,iBAAY;E1CooPpB;AACF;;AC1gQE;EyCmXA;IAqBQ,iBAAY;E1CuoPpB;AACF;;AC5gQE;EyC+WA;IAwBQ,iBAAY;E1C0oPpB;AACF;;AC7gQI;EyC0WF;IA2BQ,iBAAY;E1C6oPpB;AACF;;ACzgQI;EyCgWF;IA8BQ,iBAAY;E1CgpPpB;AACF;;AC1gQI;EyC2VF;IAiCQ,iBAAY;E1CmpPpB;AACF;;ACtgQI;EyCiVF;IAoCQ,iBAAY;E1CspPpB;AACF;;A0C3rPE;EASM,oBAAY;A1CsrPpB;;AC9jQE;EyC+XA;IAYQ,oBAAY;E1CwrPpB;AACF;;AChkQE;EyC2XA;IAeQ,oBAAY;E1C2rPpB;AACF;;AClkQE;EyCuXA;IAkBQ,oBAAY;E1C8rPpB;AACF;;ACpkQE;EyCmXA;IAqBQ,oBAAY;E1CisPpB;AACF;;ACtkQE;EyC+WA;IAwBQ,oBAAY;E1CosPpB;AACF;;ACvkQI;EyC0WF;IA2BQ,oBAAY;E1CusPpB;AACF;;ACnkQI;EyCgWF;IA8BQ,oBAAY;E1C0sPpB;AACF;;ACpkQI;EyC2VF;IAiCQ,oBAAY;E1C6sPpB;AACF;;AChkQI;EyCiVF;IAoCQ,oBAAY;E1CgtPpB;AACF;;A0CrvPE;EASM,mBAAY;A1CgvPpB;;ACxnQE;EyC+XA;IAYQ,mBAAY;E1CkvPpB;AACF;;AC1nQE;EyC2XA;IAeQ,mBAAY;E1CqvPpB;AACF;;AC5nQE;EyCuXA;IAkBQ,mBAAY;E1CwvPpB;AACF;;AC9nQE;EyCmXA;IAqBQ,mBAAY;E1C2vPpB;AACF;;AChoQE;EyC+WA;IAwBQ,mBAAY;E1C8vPpB;AACF;;ACjoQI;EyC0WF;IA2BQ,mBAAY;E1CiwPpB;AACF;;AC7nQI;EyCgWF;IA8BQ,mBAAY;E1CowPpB;AACF;;AC9nQI;EyC2VF;IAiCQ,mBAAY;E1CuwPpB;AACF;;AC1nQI;EyCiVF;IAoCQ,mBAAY;E1C0wPpB;AACF;;A0C/yPE;EASM,oBAAY;A1C0yPpB;;AClrQE;EyC+XA;IAYQ,oBAAY;E1C4yPpB;AACF;;ACprQE;EyC2XA;IAeQ,oBAAY;E1C+yPpB;AACF;;ACtrQE;EyCuXA;IAkBQ,oBAAY;E1CkzPpB;AACF;;ACxrQE;EyCmXA;IAqBQ,oBAAY;E1CqzPpB;AACF;;AC1rQE;EyC+WA;IAwBQ,oBAAY;E1CwzPpB;AACF;;AC3rQI;EyC0WF;IA2BQ,oBAAY;E1C2zPpB;AACF;;ACvrQI;EyCgWF;IA8BQ,oBAAY;E1C8zPpB;AACF;;ACxrQI;EyC2VF;IAiCQ,oBAAY;E1Ci0PpB;AACF;;ACprQI;EyCiVF;IAoCQ,oBAAY;E1Co0PpB;AACF;;A0Cz2PE;EASM,iBAAY;A1Co2PpB;;AC5uQE;EyC+XA;IAYQ,iBAAY;E1Cs2PpB;AACF;;AC9uQE;EyC2XA;IAeQ,iBAAY;E1Cy2PpB;AACF;;AChvQE;EyCuXA;IAkBQ,iBAAY;E1C42PpB;AACF;;AClvQE;EyCmXA;IAqBQ,iBAAY;E1C+2PpB;AACF;;ACpvQE;EyC+WA;IAwBQ,iBAAY;E1Ck3PpB;AACF;;ACrvQI;EyC0WF;IA2BQ,iBAAY;E1Cq3PpB;AACF;;ACjvQI;EyCgWF;IA8BQ,iBAAY;E1Cw3PpB;AACF;;AClvQI;EyC2VF;IAiCQ,iBAAY;E1C23PpB;AACF;;AC9uQI;EyCiVF;IAoCQ,iBAAY;E1C83PpB;AACF;;A0Cn6PE;EASM,oBAAY;A1C85PpB;;ACtyQE;EyC+XA;IAYQ,oBAAY;E1Cg6PpB;AACF;;ACxyQE;EyC2XA;IAeQ,oBAAY;E1Cm6PpB;AACF;;AC1yQE;EyCuXA;IAkBQ,oBAAY;E1Cs6PpB;AACF;;AC5yQE;EyCmXA;IAqBQ,oBAAY;E1Cy6PpB;AACF;;AC9yQE;EyC+WA;IAwBQ,oBAAY;E1C46PpB;AACF;;AC/yQI;EyC0WF;IA2BQ,oBAAY;E1C+6PpB;AACF;;AC3yQI;EyCgWF;IA8BQ,oBAAY;E1Ck7PpB;AACF;;AC5yQI;EyC2VF;IAiCQ,oBAAY;E1Cq7PpB;AACF;;ACxyQI;EyCiVF;IAoCQ,oBAAY;E1Cw7PpB;AACF;;A0C79PE;EASM,mBAAY;A1Cw9PpB;;ACh2QE;EyC+XA;IAYQ,mBAAY;E1C09PpB;AACF;;ACl2QE;EyC2XA;IAeQ,mBAAY;E1C69PpB;AACF;;ACp2QE;EyCuXA;IAkBQ,mBAAY;E1Cg+PpB;AACF;;ACt2QE;EyCmXA;IAqBQ,mBAAY;E1Cm+PpB;AACF;;ACx2QE;EyC+WA;IAwBQ,mBAAY;E1Cs+PpB;AACF;;ACz2QI;EyC0WF;IA2BQ,mBAAY;E1Cy+PpB;AACF;;ACr2QI;EyCgWF;IA8BQ,mBAAY;E1C4+PpB;AACF;;ACt2QI;EyC2VF;IAiCQ,mBAAY;E1C++PpB;AACF;;ACl2QI;EyCiVF;IAoCQ,mBAAY;E1Ck/PpB;AACF;;A0CvhQE;EASM,oBAAY;A1CkhQpB;;AC15QE;EyC+XA;IAYQ,oBAAY;E1CohQpB;AACF;;AC55QE;EyC2XA;IAeQ,oBAAY;E1CuhQpB;AACF;;AC95QE;EyCuXA;IAkBQ,oBAAY;E1C0hQpB;AACF;;ACh6QE;EyCmXA;IAqBQ,oBAAY;E1C6hQpB;AACF;;ACl6QE;EyC+WA;IAwBQ,oBAAY;E1CgiQpB;AACF;;ACn6QI;EyC0WF;IA2BQ,oBAAY;E1CmiQpB;AACF;;AC/5QI;EyCgWF;IA8BQ,oBAAY;E1CsiQpB;AACF;;ACh6QI;EyC2VF;IAiCQ,oBAAY;E1CyiQpB;AACF;;AC55Q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E,yBAA6B;A7C+zRnC;;A6C9zRI;EAGI,yBAAgD;A7C+zRxD;;A6C9zRI;EACE,oCAAwC;A7Ci0R9C;;A6C71RE;EACE,yBAAwB;A7Cg2R5B;;A6C/1RE;EAGI,yBAA0C;A7Cg2RhD;;A6C/1RE;EACE,oCAAmC;A7Ck2RvC;;A6C71RI;EACE,yBAA8B;A7Cg2RpC;;A6C/1RI;EAGI,yBAAgD;A7Cg2RxD;;A6C/1RI;EACE,oCAAyC;A7Ck2R/C;;A6Ch2RI;EACE,yBAA6B;A7Cm2RnC;;A6Cl2RI;EAGI,yBAAgD;A7Cm2RxD;;A6Cl2RI;EACE,oCAAwC;A7Cq2R9C;;A6Cj4RE;EACE,yBAAwB;A7Co4R5B;;A6Cn4RE;EAGI,yBAA0C;A7Co4RhD;;A6Cn4RE;EACE,oCAAmC;A7Cs4RvC;;A6Cj4RI;EACE,yBAA8B;A7Co4RpC;;A6Cn4RI;EAGI,yBAAgD;A7Co4RxD;;A6Cn4RI;EACE,oCAAyC;A7Cs4R/C;;A6Cp4RI;EACE,yBAA6B;A7Cu4RnC;;A6Ct4RI;EAGI,yBAAgD;A7Cu4RxD;;A6Ct4RI;EACE,oCAAwC;A7Cy4R9C;;A6Cr6RE;EACE,yBAAwB;A7Cw6R5B;;A6Cv6RE;EAGI,yBAA0C;A7Cw6RhD;;A6Cv6RE;EACE,oCAAmC;A7C06RvC;;A6Cr6RI;EACE,yBAA8B;A7Cw6RpC;;A6Cv6RI;EAGI,yBAAgD;A7Cw6RxD;;A6Cv6RI;EACE,oCAAyC;A7C06R/C;;A6Cx6RI;EACE,yBAA6B;A7C26RnC;;A6C16RI;EAGI,yBAAgD;A7C26RxD;;A6C16RI;EACE,oCAAwC;A7C66R9C;;A6C16RE;EACE,yBAAwB;A7C66R5B;;A6C56RE;EACE,oCAAmC;A7C+6RvC;;A6Cl7RE;EACE,yBAAwB;A7Cq7R5B;;A6Cp7RE;EACE,oCAAmC;A7Cu7RvC;;A6C17RE;EACE,yBAAwB;A7C67R5B;;A6C57RE;EACE,oCAAmC;A7C+7RvC;;A6Cl8RE;EACE,yBAAwB;A7Cq8R5B;;A6Cp8RE;EACE,oCAAmC;A7Cu8RvC;;A6C18RE;EACE,yBAAwB;A7C68R5B;;A6C58RE;EACE,oCAAmC;A7C+8RvC;;A6Cl9RE;EACE,yBAAwB;A7Cq9R5B;;A6Cp9RE;EACE,oCAAmC;A7Cu9RvC;;A6C19RE;EACE,yBAAwB;A7C69R5B;;A6C59RE;EACE,oCAAmC;A7C+9RvC;;A6Cl+RE;EACE,4BAAwB;A7Cq+R5B;;A6Cp+RE;EACE,uCAAmC;A7Cu+RvC;;A6C1+RE;EACE,yBAAwB;A7C6+R5B;;A6C5+RE;EACE,oCAAmC;A7C++RvC;;A8CnhSE;EACE,8BAAiC;A9CshSrC;;A8CvhSE;EACE,sCAAiC;A9C0hSrC;;A8C3hSE;EACE,iCAAiC;A9C8hSrC;;A8C/hSE;EACE,yCAAiC;A9CkiSrC;;A8C9hSE;EACE,4BAA4B;A9CiiShC;;A8CliSE;EACE,0BAA4B;A9CqiShC;;A8CtiSE;EACE,kCAA4B;A9CyiShC;;A8CriSE;EACE,sCAAkC;A9CwiStC;;A8CziSE;EACE,oCAAkC;A9C4iStC;;A8C7iSE;EACE,kCAAkC;A9CgjStC;;A8CjjSE;EACE,yCAAkC;A9CojStC;;A8CrjSE;EACE,wCAAkC;A9CwjStC;;A8CzjSE;EACE,wCAAkC;A9C4jStC;;A8C7jSE;EACE,iCAAkC;A9CgkStC;;A8CjkSE;EACE,+BAAkC;A9CokStC;;A8CrkSE;EACE,gCAAkC;A9CwkStC;;A8CzkSE;EACE,iCAAkC;A9C4kStC;;A8CxkSE;EACE,oCAAgC;A9C2kSpC;;A8C5kSE;EACE,kCAAgC;A9C+kSpC;;A8ChlSE;EACE,gCAAgC;A9CmlSpC;;A8CplSE;EACE,uCAAgC;A9CulSpC;;A8CxlSE;EACE,sCAAgC;A9C2lSpC;;A8C5lSE;EACE,sCAAgC;A9C+lSpC;;A8ChmSE;EACE,iCAAgC;A9CmmSpC;;A8CpmSE;EACE,+BAAgC;A9CumSpC;;A8CxmSE;EACE,6BAAgC;A9C2mSpC;;A8C5mSE;EACE,kCAAgC;A9C+mSpC;;A8C3mSE;EACE,+BAA8B;A9C8mSlC;;A8C/mSE;EACE,kCAA8B;A9CknSlC;;A8CnnSE;EACE,gCAA8B;A9CsnSlC;;A8CvnSE;EACE,8BAA8B;A9C0nSlC;;A8C3nSE;EACE,gCAA8B;A9C8nSlC;;A8C/nSE;EAC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A2B;ApD0vTjC;;AoD3vTI;EACE,0BAA2B;ApD8vTjC;;AoD/vTI;EACE,4BAA2B;ApDkwTjC;;AoDnwTI;EACE,6BAA2B;ApDswTjC;;AoDvwTI;EACE,0BAA2B;ApD0wTjC;;AoD3wTI;EACE,6BAA2B;ApD8wTjC;;ACvrTE;EmDxFE;IACE,0BAA2B;EpDmxT/B;EoDpxTE;IACE,4BAA2B;EpDsxT/B;EoDvxTE;IACE,0BAA2B;EpDyxT/B;EoD1xTE;IACE,4BAA2B;EpD4xT/B;EoD7xTE;IACE,6BAA2B;EpD+xT/B;EoDhyTE;IACE,0BAA2B;EpDkyT/B;EoDnyTE;IACE,6BAA2B;EpDqyT/B;AACF;;AC3sTE;EmD5FE;IACE,0BAA2B;EpD2yT/B;EoD5yTE;IACE,4BAA2B;EpD8yT/B;EoD/yTE;IACE,0BAA2B;EpDizT/B;EoDlzTE;IACE,4BAA2B;EpDozT/B;EoDrzTE;IACE,6BAA2B;EpDuzT/B;EoDxzTE;IACE,0BAA2B;EpD0zT/B;EoD3zTE;IACE,6BAA2B;EpD6zT/B;AACF;;AC3tTE;EmDpGE;IACE,0BAA2B;EpDm0T/B;EoDp0TE;IACE,4BAA2B;EpDs0T/B;EoDv0TE;IACE,0BAA2B;EpDy0T/B;EoD10TE;IACE,4BAA2B;EpD40T/B;EoD70TE;IACE,6BAA2B;EpD+0T/B;EoDh1TE;IACE,0BAA2B;EpDk1T/B;EoDn1TE;IACE,6BAA2B;EpDq1T/B;AACF;;AC/uTE;EmDxGE;IACE,0BAA2B;EpD21T/B;EoD51TE;IACE,4BAA2B;EpD81T/B;EoD/1TE;IACE,0BAA2B;EpDi2T/B;EoDl2TE;IACE,4BAA2B;EpDo2T/B;EoDr2TE;IACE,6BAA2B;EpDu2T/B;EoDx2TE;IACE,0BAA2B;EpD02T/B;EoD32TE;IACE,6BAA2B;EpD62T/B;AACF;;ACxvTI;EmDvHA;IACE,0BAA2B;EpDm3T/B;EoDp3TE;IACE,4BAA2B;EpDs3T/B;EoDv3TE;IACE,0BAA2B;EpDy3T/B;EoD13TE;IACE,4BAA2B;EpD43T/B;EoD73TE;IACE,6BAA2B;EpD+3T/B;EoDh4TE;IACE,0BAA2B;EpDk4T/B;EoDn4TE;IACE,6BAA2B;EpDq4T/B;AACF;;ACjwTI;EmDtIA;IACE,0BAA2B;EpD24T/B;EoD54TE;IACE,4BAA2B;EpD84T/B;EoD/4TE;IACE,0BAA2B;EpDi5T/B;EoDl5TE;IACE,4BAA2B;EpDo5T/B;EoDr5TE;IACE,6BAA2B;EpDu5T/B;EoDx5TE;IACE,0BAA2B;EpD05T/B;EoD35TE;IACE,6BAA2B;EpD65T/B;AACF;;AoDr4TE;EACE,6BAAqC;ApDw4TzC;;AoDz4TE;EACE,8BAAqC;ApD44TzC;;AoD74TE;EACE,2BAAqC;ApDg5TzC;;AoDj5TE;EACE,4BAAqC;ApDo5TzC;;ACv1TE;EmDzDE;IACE,6BAAqC;EpDo5TzC;AACF;;ACz1TE;EmD1DE;IACE,6BAAqC;EpDu5TzC;AACF;;AC31TE;EmD3DE;IACE,6BAAqC;EpD05TzC;AACF;;AC71TE;EmD5DE;IACE,6BAAqC;EpD65TzC;AACF;;AC/1TE;EmD7DE;IACE,6BAAqC;EpDg6TzC;AACF;;ACh2TI;EmD/DA;IACE,6BAAqC;EpDm6TzC;AACF;;AC51TI;EmDtEA;IACE,6BAAqC;EpDs6TzC;AACF;;AC71TI;EmDxEA;IACE,6BAAqC;EpDy6TzC;AACF;;ACz1TI;EmD/EA;IACE,6BAAqC;EpD46TzC;AACF;;AC74TE;EmDzDE;IACE,8BAAqC;EpD08TzC;AACF;;AC/4TE;EmD1DE;IACE,8BAAqC;EpD68TzC;AACF;;ACj5TE;EmD3DE;IACE,8BAAqC;EpDg9TzC;AACF;;ACn5TE;EmD5DE;IACE,8BAAqC;EpDm9TzC;AACF;;ACr5TE;EmD7DE;IACE,8BAAqC;EpDs9TzC;AACF;;ACt5TI;EmD/DA;IACE,8BAAqC;EpDy9TzC;AACF;;ACl5TI;EmDtEA;IACE,8BAAqC;EpD49TzC;AACF;;ACn5TI;EmDxEA;IACE,8BAAqC;EpD+9TzC;AACF;;AC/4TI;EmD/EA;IACE,8BAAqC;EpDk+TzC;AACF;;ACn8TE;EmDzDE;IACE,2BAAqC;EpDggUzC;AACF;;ACr8TE;EmD1DE;IACE,2BAAqC;EpDmgUzC;AACF;;ACv8TE;EmD3DE;IACE,2BAAqC;EpDsgUzC;AACF;;ACz8TE;EmD5DE;IACE,2BAAqC;EpDygUzC;AACF;;AC38TE;EmD7DE;IACE,2BAAqC;EpD4gUzC;AACF;;AC58TI;EmD/DA;IACE,2BAAqC;EpD+gUzC;AACF;;ACx8TI;EmDtEA;IACE,2BAAqC;EpDkhUzC;AACF;;ACz8TI;EmDxEA;IACE,2BAAqC;EpDqhUzC;AACF;;ACr8TI;EmD/EA;IACE,2BAAqC;EpDwhUzC;AACF;;ACz/TE;EmDzDE;IACE,4BAAqC;EpDsjUzC;AACF;;AC3/TE;EmD1DE;IACE,4BAAqC;EpDyjUzC;AACF;;AC7/TE;EmD3DE;IACE,4BAAqC;EpD4jUzC;AACF;;AC//TE;EmD5DE;IACE,4BAAqC;EpD+jUzC;AACF;;ACjgUE;EmD7DE;IACE,4BAAqC;EpDkkUzC;AACF;;AClgUI;EmD/DA;IACE,4BAAqC;EpDqkUzC;AACF;;AC9/TI;EmDtEA;IACE,4BAAqC;EpDwkUzC;AACF;;AC//TI;EmDxEA;IACE,4BAAqC;EpD2kUzC;AACF;;AC3/TI;EmD/EA;IACE,4BAAqC;EpD8kUzC;AACF;;AoD7kUA;EACE,qCAAqC;ApDglUvC;;AoD9kUA;EACE,oCAAoC;ApDilUtC;;AoD/kUA;EACE,oCAAoC;ApDklUtC;;AoDhlUA;EACE,6BAA6B;ApDmlU/B;;AoDjlUA;EACE,qCAAqC;ApDolUvC;;AoDllUA;EACE,2BAAqC;ApDqlUvC;;AoDplUA;EACE,2BAAsC;ApDulUxC;;AoDtlUA;EACE,2BAAsC;ApDylUxC;;AoDxlUA;EACE,2BAAwC;ApD2lU1C;;AoD1lUA;EACE,2BAAoC;ApD6lUtC;;AoD3lUA;EACE,+LAAuC;ApD8lUzC;;AoD5lUA;EACE,+LAAyC;ApD+lU3C;;AoD7lUA;EACE,+LAA0C;ApDgmU5C;;AoD9lUA;EACE,iCAAyC;ApDimU3C;;AoD/lUA;EACE,iCAAoC;ApDkmUtC;;AqDnsUE;EACE,yBAA+B;ArDssUnC;;AC/mUE;EoDrFE;IACE,yBAA+B;ErDwsUnC;AACF;;ACjnUE;EoDtFE;IACE,yBAA+B;ErD2sUnC;AACF;;ACnnUE;EoDvFE;IACE,yBAA+B;ErD8sUnC;AACF;;ACrnUE;EoDxFE;IACE,yBAA+B;ErDitUnC;AACF;;ACvnUE;EoDzFE;IACE,yBAA+B;ErDotUnC;AACF;;ACxnUI;EoD3FA;IACE,yBAA+B;ErDutUnC;AACF;;ACpnUI;EoDlGA;IACE,yBAA+B;ErD0tUnC;AACF;;ACrnUI;EoDpGA;IACE,yBAA+B;ErD6tUnC;AACF;;ACjnUI;EoD3GA;IACE,yBAA+B;ErDguUnC;AACF;;AqD7vUE;EACE,wBAA+B;ArDgwUnC;;ACzqUE;EoDrFE;IACE,wBAA+B;ErDkwUnC;AACF;;AC3qUE;EoDtFE;IACE,wBAA+B;ErDqwUnC;AACF;;AC7qUE;EoDvFE;IACE,wBAA+B;ErDwwUnC;AACF;;AC/qUE;EoDxFE;IACE,wBAA+B;ErD2wUnC;AACF;;ACjrUE;EoDzFE;IACE,wBAA+B;ErD8wUnC;AACF;;AClrUI;EoD3FA;IACE,wBAA+B;ErDixUnC;AACF;;AC9qUI;EoDlGA;IACE,wBAA+B;ErDoxUnC;AACF;;AC/qUI;EoDpGA;IACE,wBAA+B;ErDuxUnC;AACF;;AC3qUI;EoD3GA;IACE,wBAA+B;ErD0xUnC;AACF;;AqDvzUE;EACE,0BAA+B;ArD0zUnC;;ACnuUE;EoDrFE;IACE,0BAA+B;ErD4zUnC;AACF;;ACruUE;EoDtFE;IACE,0BAA+B;ErD+zUnC;AACF;;ACvuUE;EoDvFE;IACE,0BAA+B;ErDk0UnC;AACF;;ACzuUE;EoDxFE;IACE,0BAA+B;ErDq0UnC;AACF;;AC3uUE;EoDzFE;IACE,0BAA+B;ErDw0UnC;AACF;;AC5uUI;EoD3FA;IACE,0BAA+B;ErD20UnC;AACF;;ACxuUI;EoDlGA;IACE,0BAA+B;ErD80UnC;AACF;;ACzuUI;EoDpGA;IACE,0BAA+B;ErDi1UnC;AACF;;ACruUI;EoD3GA;IACE,0BAA+B;ErDo1UnC;AACF;;AqDj3UE;EACE,gCAA+B;ArDo3UnC;;AC7xUE;EoDrFE;IACE,gCAA+B;ErDs3UnC;AACF;;AC/xUE;EoDtFE;IACE,gCAA+B;ErDy3UnC;AACF;;ACjyUE;EoDvFE;IACE,gCAA+B;ErD43UnC;AACF;;ACnyUE;EoDxFE;IACE,gCAA+B;ErD+3UnC;AACF;;ACryUE;EoDzFE;IACE,gCAA+B;ErDk4UnC;AACF;;ACtyUI;EoD3FA;IACE,gCAA+B;ErDq4UnC;AACF;;AClyUI;EoDlGA;IACE,gCAA+B;ErDw4UnC;AACF;;ACnyUI;EoDpGA;IACE,gCAA+B;ErD24UnC;AACF;;AC/xUI;EoD3GA;IACE,gCAA+B;ErD84UnC;AACF;;AqD36UE;EACE,+BAA+B;ArD86UnC;;ACv1UE;EoDrFE;IACE,+BAA+B;ErDg7UnC;AACF;;ACz1UE;EoDtFE;IACE,+BAA+B;ErDm7UnC;AACF;;AC31UE;EoDvFE;IACE,+BAA+B;ErDs7UnC;AACF;;AC71UE;EoDxFE;IACE,+BAA+B;ErDy7UnC;AACF;;AC/1UE;EoDzFE;IACE,+BAA+B;ErD47UnC;AACF;;ACh2UI;EoD3FA;IACE,+BAA+B;ErD+7UnC;AACF;;AC51UI;EoDlGA;IACE,+BAA+B;ErDk8UnC;AACF;;AC71UI;EoDpGA;IACE,+BAA+B;ErDq8UnC;AACF;;ACz1UI;EoD3GA;IACE,+BAA+B;ErDw8UnC;AACF;;AqDv8UA;EACE,wBAAwB;ArD08U1B;;AqDx8UA;EACE,uBAAuB;EACvB,iCAAiC;EACjC,yBAAyB;EACzB,2BAA2B;EAC3B,qBAAqB;EACrB,6BAA6B;EAC7B,8BAA8B;EAC9B,wBAAwB;ArD28U1B;;AC55UE;EoD5CA;IACE,wBAAwB;ErD48U1B;AACF;;AC95UE;EoD5CA;IACE,wBAAwB;ErD88U1B;AACF;;ACh6UE;EoD5CA;IACE,wBAAwB;ErDg9U1B;AACF;;ACl6UE;EoD5CA;IACE,wBAAwB;ErDk9U1B;AACF;;ACp6UE;EoD5CA;IACE,wBAAwB;ErDo9U1B;AACF;;ACr6UI;EoD7CF;IACE,wBAAwB;ErDs9U1B;AACF;;ACj6UI;EoDnDF;IACE,wBAAwB;ErDw9U1B;AACF;;ACl6UI;EoDpDF;IACE,wBAAwB;ErD09U1B;AACF;;AC95UI;EoD1DF;IACE,wBAAwB;ErD49U1B;AACF;;AqD39UA;EACE,6BAA6B;ArD89U/B;;ACt9UE;EoDLA;IACE,6BAA6B;ErD+9U/B;AACF;;ACx9UE;EoDLA;IACE,6BAA6B;ErDi+U/B;AACF;;AC19UE;EoDLA;IACE,6BAA6B;ErDm+U/B;AACF;;AC59UE;EoDLA;IACE,6BAA6B;ErDq+U/B;AACF;;AC99UE;EoDLA;IACE,6BAA6B;ErDu+U/B;AACF;;AC/9UI;EoDNF;IACE,6BAA6B;ErDy+U/B;AACF;;AC39UI;EoDZF;IACE,6BAA6B;ErD2+U/B;AACF;;AC59UI;EoDbF;IACE,6BAA6B;ErD6+U/B;AACF;;ACx9UI;EoDnBF;IACE,6BAA6B;ErD++U/B;AACF;;AsDzmVA,iBAAA;ACWA;EACE,oBAAoB;EACpB,aAAa;EACb,sBAAsB;EACtB,8BAA8B;AvDkmVhC;;AuDtmVA;EAMI,gBAAgB;AvDomVpB;;AuD1mVA;EASM,mBAAmB;AvDqmVzB;;AuD9mVA;EAeM,uBxDXyB;EwDYzB,cxDzBuB;AC4nV7B;;AuDnnVA;;EAmBQ,cAAc;AvDqmVtB;;AuDxnVA;EAqBQ,cxD9BqB;ACqoV7B;;AuD5nVA;EAuBQ,4BxDhCqB;ACyoV7B;;AuDhoVA;;EA0BU,cxDnCmB;AC8oV7B;;ACviVE;EsD9FF;IA6BU,uBxDzBqB;ECsoV7B;AACF;;AuD3oVA;;EAgCQ,4BxDzCqB;ACypV7B;;AuDhpVA;;;EAqCU,yB7C6DuB;E6C5DvB,cxD/CmB;ACgqV7B;;AuDvpVA;EAyCU,cxDlDmB;EwDmDnB,YAAY;AvDknVtB;;AuD5pVA;EA4CY,UAAU;AvDonVtB;;AuDhqVA;EA+CY,uBAAwB;EACxB,UAAU;AvDqnVtB;;AuDrqVA;EAoDY,cxD7DiB;ACkrV7B;;AuDzqVA;EAsDc,uCxD/De;ACsrV7B;;AuD7qVA;EA0Dc,yBxDnEe;EwDoEf,qBxDpEe;EwDqEf,YxDxDiB;AC+qV/B;;AuDnrVA;EAkEU,4EAAyG;AvDqnVnH;;ACrmVE;EsDlFF;IAqEc,4EAAyG;EvDunVrH;AACF;;AuD7rVA;EAeM,yBxDxBuB;EwDyBvB,YxDZyB;AC8rV/B;;AuDlsVA;;EAmBQ,cAAc;AvDorVtB;;AuDvsVA;EAqBQ,YxDjBuB;ACusV/B;;AuD3sVA;EAuBQ,+BxDnBuB;AC2sV/B;;AuD/sVA;;EA0BU,YxDtBqB;ACgtV/B;;ACtnVE;EsD9FF;IA6BU,yBxDtCmB;ECkuV3B;AACF;;AuD1tVA;;EAgCQ,+BxD5BuB;AC2tV/B;;AuD/tVA;;;EAqCU,uB7C6DuB;E6C5DvB,YxDlCqB;ACkuV/B;;AuDtuVA;EAyCU,YxDrCqB;EwDsCrB,YAAY;AvDisVtB;;AuD3uVA;EA4CY,UAAU;AvDmsVtB;;AuD/uVA;EA+CY,yBAAwB;EACxB,UAAU;AvDosVtB;;AuDpvVA;EAoDY,YxDhDmB;ACovV/B;;AuDxvVA;EAsDc,uCxD/De;ACqwV7B;;AuD5vVA;EA0Dc,uBxDtDiB;EwDuDjB,mBxDvDiB;EwDwDjB,cxDrEe;AC2wV7B;;AuDlwVA;EAkEU,8EAAyG;AvDosVnH;;ACprVE;EsDlFF;IAqEc,8EAAyG;EvDssVrH;AACF;;AuD5wVA;EAeM,4BxDbwB;EwDcxB,yB7CqDe;AV4sVrB;;AuDjxVA;;EAmBQ,cAAc;AvDmwVtB;;AuDtxVA;EAqBQ,yB7CgDa;AVqtVrB;;AuD1xVA;EAuBQ,yB7C8Ca;AVytVrB;;AuD9xVA;;EA0BU,yB7C2CW;AV8tVrB;;ACrsVE;EsD9FF;IA6BU,4BxD3BoB;ECsyV5B;AACF;;AuDzyVA;;EAgCQ,yB7CqCa;AVyuVrB;;AuD9yVA;;;EAqCU,yB7C6DuB;E6C5DvB,yB7C+BW;AVgvVrB;;AuDrzVA;EAyCU,yB7C4BW;E6C3BX,YAAY;AvDgxVtB;;AuD1zVA;EA4CY,UAAU;AvDkxVtB;;AuD9zVA;EA+CY,4BAAwB;EACxB,UAAU;AvDmxVtB;;AuDn0VA;EAoDY,yB7CiBS;AVkwVrB;;AuDv0VA;EAsDc,uCxD/De;ACo1V7B;;AuD30VA;EA0Dc,oC7CWO;E6CVP,gC7CUO;E6CTP,iBxD1DgB;AC+0V9B;;AuDj1VA;EAkEU,iFAAyG;AvDmxVnH;;ACnwVE;EsDlFF;IAqEc,iFAAyG;EvDqxVrH;AACF;;AuD31VA;EAeM,yBxDpBwB;EwDqBxB,W7CuDU;AVyxVhB;;AuDh2VA;;EAmBQ,cAAc;AvDk1VtB;;AuDr2VA;EAqBQ,W7CkDQ;AVkyVhB;;AuDz2VA;EAuBQ,+B7CgDQ;AVsyVhB;;AuD72VA;;EA0BU,W7C6CM;AV2yVhB;;ACpxVE;EsD9FF;IA6BU,yBxDlCoB;EC43V5B;AACF;;AuDx3VA;;EAgCQ,+B7CuCQ;AVszVhB;;AuD73VA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV6zVhB;;AuDp4VA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD+1VtB;;AuDz4VA;EA4CY,UAAU;AvDi2VtB;;AuD74VA;EA+CY,yBAAwB;EACxB,UAAU;AvDk2VtB;;AuDl5VA;EAoDY,W7CmBI;AV+0VhB;;AuDt5VA;EAsDc,uCxD/De;ACm6V7B;;AuD15VA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDjEgB;ACq6V9B;;AuDh6VA;EAkEU,gFAAyG;AvDk2VnH;;ACl1VE;EsDlFF;IAqEc,gFAAyG;EvDo2VrH;AACF;;AuD16VA;EAeM,yBxDN4B;EwDO5B,W7CuDU;AVw2VhB;;AuD/6VA;;EAmBQ,cAAc;AvDi6VtB;;AuDp7VA;EAqBQ,W7CkDQ;AVi3VhB;;AuDx7VA;EAuBQ,+B7CgDQ;AVq3VhB;;AuD57VA;;EA0BU,W7C6CM;AV03VhB;;ACn2VE;EsD9FF;IA6BU,yBxDpBwB;EC67VhC;AACF;;AuDv8VA;;EAgCQ,+B7CuCQ;AVq4VhB;;AuD58VA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV44VhB;;AuDn9VA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD86VtB;;AuDx9VA;EA4CY,UAAU;AvDg7VtB;;AuD59VA;EA+CY,yBAAwB;EACxB,UAAU;AvDi7VtB;;AuDj+VA;EAoDY,W7CmBI;AV85VhB;;AuDr+VA;EAsDc,uCxD/De;ACk/V7B;;AuDz+VA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDnDoB;ACs+VlC;;AuD/+VA;EAkEU,gFAAyG;AvDi7VnH;;ACj6VE;EsDlFF;IAqEc,gFAAyG;EvDm7VrH;AACF;;AuDz/VA;EAeM,yBxDJ4B;EwDK5B,W7CuDU;AVu7VhB;;AuD9/VA;;EAmBQ,cAAc;AvDg/VtB;;AuDngWA;EAqBQ,W7CkDQ;AVg8VhB;;AuDvgWA;EAuBQ,+B7CgDQ;AVo8VhB;;AuD3gWA;;EA0BU,W7C6CM;AVy8VhB;;ACl7VE;EsD9FF;IA6BU,yBxDlBwB;EC0gWhC;AACF;;AuDthWA;;EAgCQ,+B7CuCQ;AVo9VhB;;AuD3hWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV29VhB;;AuDliWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD6/VtB;;AuDviWA;EA4CY,UAAU;AvD+/VtB;;AuD3iWA;EA+CY,yBAAwB;EACxB,UAAU;AvDggWtB;;AuDhjWA;EAoDY,W7CmBI;AV6+VhB;;AuDpjWA;EAsDc,uCxD/De;ACikW7B;;AuDxjWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDjDoB;ACmjWlC;;AuD9jWA;EAkEU,gFAAyG;AvDggWnH;;ACh/VE;EsDlFF;IAqEc,gFAAyG;EvDkgWrH;AACF;;AuDxkWA;EAeM,yBxDL4B;EwDM5B,W7CuDU;AVsgWhB;;AuD7kWA;;EAmBQ,cAAc;AvD+jWtB;;AuDllWA;EAqBQ,W7CkDQ;AV+gWhB;;AuDtlWA;EAuBQ,+B7CgDQ;AVmhWhB;;AuD1lWA;;EA0BU,W7C6CM;AVwhWhB;;ACjgWE;EsD9FF;IA6BU,yBxDnBwB;EC0lWhC;AACF;;AuDrmWA;;EAgCQ,+B7CuCQ;AVmiWhB;;AuD1mWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV0iWhB;;AuDjnWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD4kWtB;;AuDtnWA;EA4CY,UAAU;AvD8kWtB;;AuD1nWA;EA+CY,yBAAwB;EACxB,UAAU;AvD+kWtB;;AuD/nWA;EAoDY,W7CmBI;AV4jWhB;;AuDnoWA;EAsDc,uCxD/De;ACgpW7B;;AuDvoWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDlDoB;ACmoWlC;;AuD7oWA;EAkEU,gFAAyG;AvD+kWnH;;AC/jWE;EsDlFF;IAqEc,gFAAyG;EvDilWrH;AACF;;AuDvpWA;EAeM,yBxDP4B;EwDQ5B,W7CuDU;AVqlWhB;;AuD5pWA;;EAmBQ,cAAc;AvD8oWtB;;AuDjqWA;EAqBQ,W7CkDQ;AV8lWhB;;AuDrqWA;EAuBQ,+B7CgDQ;AVkmWhB;;AuDzqWA;;EA0BU,W7C6CM;AVumWhB;;AChlWE;EsD9FF;IA6BU,yBxDrBwB;EC2qWhC;AACF;;AuDprWA;;EAgCQ,+B7CuCQ;AVknWhB;;AuDzrWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AVynWhB;;AuDhsWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD2pWtB;;AuDrsWA;EA4CY,UAAU;AvD6pWtB;;AuDzsWA;EA+CY,yBAAwB;EACxB,UAAU;AvD8pWtB;;AuD9sWA;EAoDY,W7CmBI;AV2oWhB;;AuDltWA;EAsDc,uCxD/De;AC+tW7B;;AuDttWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDpDoB;ACotWlC;;AuD5tWA;EAkEU,gFAAyG;AvD8pWnH;;AC9oWE;EsDlFF;IAqEc,gFAAyG;EvDgqWrH;AACF;;AuDtuWA;EAeM,yBxDR4B;EwDS5B,yB7CqDe;AVsqWrB;;AuD3uWA;;EAmBQ,cAAc;AvD6tWtB;;AuDhvWA;EAqBQ,yB7CgDa;AV+qWrB;;AuDpvWA;EAuBQ,yB7C8Ca;AVmrWrB;;AuDxvWA;;EA0BU,yB7C2CW;AVwrWrB;;AC/pWE;EsD9FF;IA6BU,yBxDtBwB;EC2vWhC;AACF;;AuDnwWA;;EAgCQ,yB7CqCa;AVmsWrB;;AuDxwWA;;;EAqCU,yB7C6DuB;E6C5DvB,yB7C+BW;AV0sWrB;;AuD/wWA;EAyCU,yB7C4BW;E6C3BX,YAAY;AvD0uWtB;;AuDpxWA;EA4CY,UAAU;AvD4uWtB;;AuDxxWA;EA+CY,yBAAwB;EACxB,UAAU;AvD6uWtB;;AuD7xWA;EAoDY,yB7CiBS;AV4tWrB;;AuDjyWA;EAsDc,uCxD/De;AC8yW7B;;AuDryWA;EA0Dc,oC7CWO;E6CVP,gC7CUO;E6CTP,cxDrDoB;ACoyWlC;;AuD3yWA;EAkEU,gFAAyG;AvD6uWnH;;AC7tWE;EsDlFF;IAqEc,gFAAyG;EvD+uWrH;AACF;;AuDrzWA;EAeM,yBxDF2B;EwDG3B,W7CuDU;AVmvWhB;;AuD1zWA;;EAmBQ,cAAc;AvD4yWtB;;AuD/zWA;EAqBQ,W7CkDQ;AV4vWhB;;AuDn0WA;EAuBQ,+B7CgDQ;AVgwWhB;;AuDv0WA;;EA0BU,W7C6CM;AVqwWhB;;AC9uWE;EsD9FF;IA6BU,yBxDhBuB;ECo0W/B;AACF;;AuDl1WA;;EAgCQ,+B7CuCQ;AVgxWhB;;AuDv1WA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AVuxWhB;;AuD91WA;EAyCU,W7C8BM;E6C7BN,YAAY;AvDyzWtB;;AuDn2WA;EA4CY,UAAU;AvD2zWtB;;AuDv2WA;EA+CY,yBAAwB;EACxB,UAAU;AvD4zWtB;;AuD52WA;EAoDY,W7CmBI;AVyyWhB;;AuDh3WA;EAsDc,uCxD/De;AC63W7B;;AuDp3WA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxD/CmB;AC62WjC;;AuD13WA;EAkEU,gFAAyG;AvD4zWnH;;AC5yWE;EsDlFF;IAqEc,gFAAyG;EvD8zWrH;AACF;;AuDp4WA;EAyEM,eAhF0B;AvD+4WhC;;AClzWE;EsDtFF;IA6EQ,oBAnF8B;EvDm5WpC;AACF;;ACxzWE;EsDtFF;IAiFQ,mBAtF4B;EvDw5WlC;AACF;;AuDp5WA;EAsFM,mBAAmB;EACnB,aAAa;AvDk0WnB;;AuDz5WA;EAyFQ,YAAY;EACZ,cAAc;AvDo0WtB;;AuD95WA;EA4FI,gBAAgB;AvDs0WpB;;AuDl6WA;EA8FI,iBAAiB;AvDw0WrB;;AuDp0WA;EAEE,gBAAgB;AvDs0WlB;;AuDx0WA;EAII,SAAS;EACT,gBAAgB;EAChB,eAAe;EACf,kBAAkB;EAClB,QAAQ;EACR,qCAAqC;AvDw0WzC;;AuDj1WA;EAYI,YAAY;AvDy0WhB;;ACr2WE;EsDgBF;IAeI,aAAa;EvD20Wf;AACF;;AuD10WA;EACE,kBAAkB;AvD60WpB;;AC/2WE;EsDiCF;IAKM,aAAa;EvD80WjB;EuDn1WF;IAOQ,sBAAsB;EvD+0W5B;AACF;;ACp3WE;EsD6BF;IASI,aAAa;IACb,uBAAuB;EvDm1WzB;EuD71WF;ItD4BI,mBsDhBwC;EvDo1W1C;AACF;;AuDj1WA;;EAEE,YAAY;EACZ,cAAc;AvDo1WhB;;AuDl1WA;EACE,YAAY;EACZ,cAAc;EACd,oBApJ6B;AvDy+W/B;;AC14WE;EsDkDF;IAKI,kBArJgC;EvD6+WlC;AACF;;AwD1+WA;EACE,oBAN2B;AxDm/W7B;;ACx4WE;EuDtGF;IAII,kBAR+B;ExDu/WjC;EwDn/WF;IAOM,oBAV8B;ExDy/WlC;EwDt/WF;IASM,mBAX4B;ExD2/WhC;AACF;;AyD3/WA;EACE,yB1DO4B;E0DN5B,yBAJ+B;AzDkgXjC","file":"bulma-rtl.css"} \ No newline at end of file diff --git a/pagetop/static/bulmix/css/bulma.min.css b/pagetop/static/bulmix/css/bulma.min.css new file mode 100644 index 00000000..be16f726 --- /dev/null +++ b/pagetop/static/bulmix/css/bulma.min.css @@ -0,0 +1 @@ +/*! bulma.io v0.9.3 | MIT License | github.com/jgthms/bulma */.button,.file-cta,.file-name,.input,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.select select,.textarea{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(.5em - 1px);padding-left:calc(.75em - 1px);padding-right:calc(.75em - 1px);padding-top:calc(.5em - 1px);position:relative;vertical-align:top}.button:active,.button:focus,.file-cta:active,.file-cta:focus,.file-name:active,.file-name:focus,.input:active,.input:focus,.is-active.button,.is-active.file-cta,.is-active.file-name,.is-active.input,.is-active.pagination-ellipsis,.is-active.pagination-link,.is-active.pagination-next,.is-active.pagination-previous,.is-active.textarea,.is-focused.button,.is-focused.file-cta,.is-focused.file-name,.is-focused.input,.is-focused.pagination-ellipsis,.is-focused.pagination-link,.is-focused.pagination-next,.is-focused.pagination-previous,.is-focused.textarea,.pagination-ellipsis:active,.pagination-ellipsis:focus,.pagination-link:active,.pagination-link:focus,.pagination-next:active,.pagination-next:focus,.pagination-previous:active,.pagination-previous:focus,.select select.is-active,.select select.is-focused,.select select:active,.select select:focus,.textarea:active,.textarea:focus{outline:0}.button[disabled],.file-cta[disabled],.file-name[disabled],.input[disabled],.pagination-ellipsis[disabled],.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .button,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .input,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-previous,fieldset[disabled] .select select,fieldset[disabled] .textarea{cursor:not-allowed}.breadcrumb,.button,.file,.is-unselectable,.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous,.tabs{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid transparent;border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:.625em;margin-top:-.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:.625em}.block:not(:last-child),.box:not(:last-child),.breadcrumb:not(:last-child),.content:not(:last-child),.level:not(:last-child),.message:not(:last-child),.notification:not(:last-child),.pagination:not(:last-child),.progress:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.tabs:not(:last-child),.title:not(:last-child){margin-bottom:1.5rem}.delete,.modal-close{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:0;position:relative;vertical-align:top;width:20px}.delete::after,.delete::before,.modal-close::after,.modal-close::before{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.delete::before,.modal-close::before{height:2px;width:50%}.delete::after,.modal-close::after{height:50%;width:2px}.delete:focus,.delete:hover,.modal-close:focus,.modal-close:hover{background-color:rgba(10,10,10,.3)}.delete:active,.modal-close:active{background-color:rgba(10,10,10,.4)}.is-small.delete,.is-small.modal-close{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.delete,.is-medium.modal-close{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.delete,.is-large.modal-close{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.button.is-loading::after,.control.is-loading::after,.loader,.select.is-loading::after{-webkit-animation:spinAround .5s infinite linear;animation:spinAround .5s infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.image.is-16by9 .has-ratio,.image.is-16by9 img,.image.is-1by1 .has-ratio,.image.is-1by1 img,.image.is-1by2 .has-ratio,.image.is-1by2 img,.image.is-1by3 .has-ratio,.image.is-1by3 img,.image.is-2by1 .has-ratio,.image.is-2by1 img,.image.is-2by3 .has-ratio,.image.is-2by3 img,.image.is-3by1 .has-ratio,.image.is-3by1 img,.image.is-3by2 .has-ratio,.image.is-3by2 img,.image.is-3by4 .has-ratio,.image.is-3by4 img,.image.is-3by5 .has-ratio,.image.is-3by5 img,.image.is-4by3 .has-ratio,.image.is-4by3 img,.image.is-4by5 .has-ratio,.image.is-4by5 img,.image.is-5by3 .has-ratio,.image.is-5by3 img,.image.is-5by4 .has-ratio,.image.is-5by4 img,.image.is-9by16 .has-ratio,.image.is-9by16 img,.image.is-square .has-ratio,.image.is-square img,.is-overlay,.modal,.modal-background{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:0 0;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */blockquote,body,dd,dl,dt,fieldset,figure,h1,h2,h3,h4,h5,h6,hr,html,iframe,legend,li,ol,p,pre,textarea,ul{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,::after,::before{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:hidden;overflow-y:scroll;text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:monospace}body{color:#4a4a4a;font-size:1em;font-weight:400;line-height:1.5}a{color:#485fc7;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:#f5f5f5;color:#da1039;font-size:.875em;font-weight:400;padding:.25em .5em .25em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type=checkbox],input[type=radio]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#363636;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#4a4a4a;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#363636}@-webkit-keyframes spinAround{from{transform:rotate(0)}to{transform:rotate(359deg)}}@keyframes spinAround{from{transform:rotate(0)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);color:#4a4a4a;display:block;padding:1.25rem}a.box:focus,a.box:hover{box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px #485fc7}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,.2),0 0 0 1px #485fc7}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#363636;cursor:pointer;justify-content:center;padding-bottom:calc(.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-large,.button .icon.is-medium,.button .icon.is-small{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-.5em - 1px);margin-right:calc(-.5em - 1px)}.button.is-hovered,.button:hover{border-color:#b5b5b5;color:#363636}.button.is-focused,.button:focus{border-color:#485fc7;color:#363636}.button.is-focused:not(:active),.button:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.button.is-active,.button:active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#4a4a4a;text-decoration:underline}.button.is-text.is-focused,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text:hover{background-color:#f5f5f5;color:#363636}.button.is-text.is-active,.button.is-text:active{background-color:#e8e8e8;color:#363636}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:0 0;border-color:transparent;color:#485fc7;text-decoration:none}.button.is-ghost.is-hovered,.button.is-ghost:hover{color:#485fc7;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white.is-hovered,.button.is-white:hover{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white.is-focused,.button.is-white:focus{border-color:transparent;color:#0a0a0a}.button.is-white.is-focused:not(:active),.button.is-white:focus:not(:active){box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.button.is-white.is-active,.button.is-white:active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:transparent;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-hovered,.button.is-white.is-inverted:hover{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined.is-focused,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-white.is-outlined.is-loading.is-focused::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading:hover::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined.is-focused,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined:hover{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black.is-hovered,.button.is-black:hover{background-color:#040404;border-color:transparent;color:#fff}.button.is-black.is-focused,.button.is-black:focus{border-color:transparent;color:#fff}.button.is-black.is-focused:not(:active),.button.is-black:focus:not(:active){box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.button.is-black.is-active,.button.is-black:active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:transparent;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-hovered,.button.is-black.is-inverted:hover{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined.is-focused,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-black.is-outlined.is-loading.is-focused::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined.is-focused,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined:hover{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #0a0a0a #0a0a0a!important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-hovered,.button.is-light:hover{background-color:#eee;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-focused,.button.is-light:focus{border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light.is-focused:not(:active),.button.is-light:focus:not(:active){box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.button.is-light.is-active,.button.is-light:active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:transparent;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,.7);color:#f5f5f5}.button.is-light.is-inverted.is-hovered,.button.is-light.is-inverted:hover{background-color:rgba(0,0,0,.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined.is-focused,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined:hover{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-light.is-outlined.is-loading.is-focused::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading:hover::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);color:rgba(0,0,0,.7)}.button.is-light.is-inverted.is-outlined.is-focused,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined:hover{background-color:rgba(0,0,0,.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #f5f5f5 #f5f5f5!important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);box-shadow:none;color:rgba(0,0,0,.7)}.button.is-dark{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark.is-hovered,.button.is-dark:hover{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark.is-focused,.button.is-dark:focus{border-color:transparent;color:#fff}.button.is-dark.is-focused:not(:active),.button.is-dark:focus:not(:active){box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.button.is-dark.is-active,.button.is-dark:active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],fieldset[disabled] .button.is-dark{background-color:#363636;border-color:transparent;box-shadow:none}.button.is-dark.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-hovered,.button.is-dark.is-inverted:hover{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-dark.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined.is-focused,.button.is-dark.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.button.is-dark.is-outlined:hover{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636!important}.button.is-dark.is-outlined.is-loading.is-focused::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-dark.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined.is-focused,.button.is-dark.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined:hover{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #363636 #363636!important}.button.is-dark.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary{background-color:#00d1b2;border-color:transparent;color:#fff}.button.is-primary.is-hovered,.button.is-primary:hover{background-color:#00c4a7;border-color:transparent;color:#fff}.button.is-primary.is-focused,.button.is-primary:focus{border-color:transparent;color:#fff}.button.is-primary.is-focused:not(:active),.button.is-primary:focus:not(:active){box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.button.is-primary.is-active,.button.is-primary:active{background-color:#00b89c;border-color:transparent;color:#fff}.button.is-primary[disabled],fieldset[disabled] .button.is-primary{background-color:#00d1b2;border-color:transparent;box-shadow:none}.button.is-primary.is-inverted{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted.is-hovered,.button.is-primary.is-inverted:hover{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],fieldset[disabled] .button.is-primary.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#00d1b2}.button.is-primary.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-primary.is-outlined{background-color:transparent;border-color:#00d1b2;color:#00d1b2}.button.is-primary.is-outlined.is-focused,.button.is-primary.is-outlined.is-hovered,.button.is-primary.is-outlined:focus,.button.is-primary.is-outlined:hover{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.button.is-primary.is-outlined.is-loading::after{border-color:transparent transparent #00d1b2 #00d1b2!important}.button.is-primary.is-outlined.is-loading.is-focused::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.button.is-primary.is-outlined.is-loading:focus::after,.button.is-primary.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-primary.is-outlined[disabled],fieldset[disabled] .button.is-primary.is-outlined{background-color:transparent;border-color:#00d1b2;box-shadow:none;color:#00d1b2}.button.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined.is-focused,.button.is-primary.is-inverted.is-outlined.is-hovered,.button.is-primary.is-inverted.is-outlined:focus,.button.is-primary.is-inverted.is-outlined:hover{background-color:#fff;color:#00d1b2}.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #00d1b2 #00d1b2!important}.button.is-primary.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light{background-color:#ebfffc;color:#00947e}.button.is-primary.is-light.is-hovered,.button.is-primary.is-light:hover{background-color:#defffa;border-color:transparent;color:#00947e}.button.is-primary.is-light.is-active,.button.is-primary.is-light:active{background-color:#d1fff8;border-color:transparent;color:#00947e}.button.is-link{background-color:#485fc7;border-color:transparent;color:#fff}.button.is-link.is-hovered,.button.is-link:hover{background-color:#3e56c4;border-color:transparent;color:#fff}.button.is-link.is-focused,.button.is-link:focus{border-color:transparent;color:#fff}.button.is-link.is-focused:not(:active),.button.is-link:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.button.is-link.is-active,.button.is-link:active{background-color:#3a51bb;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#485fc7;border-color:transparent;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#485fc7}.button.is-link.is-inverted.is-hovered,.button.is-link.is-inverted:hover{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#485fc7}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-link.is-outlined{background-color:transparent;border-color:#485fc7;color:#485fc7}.button.is-link.is-outlined.is-focused,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined:hover{background-color:#485fc7;border-color:#485fc7;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #485fc7 #485fc7!important}.button.is-link.is-outlined.is-loading.is-focused::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#485fc7;box-shadow:none;color:#485fc7}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined.is-focused,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined:hover{background-color:#fff;color:#485fc7}.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #485fc7 #485fc7!important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff1fa;color:#3850b7}.button.is-link.is-light.is-hovered,.button.is-link.is-light:hover{background-color:#e6e9f7;border-color:transparent;color:#3850b7}.button.is-link.is-light.is-active,.button.is-link.is-light:active{background-color:#dce0f4;border-color:transparent;color:#3850b7}.button.is-info{background-color:#3e8ed0;border-color:transparent;color:#fff}.button.is-info.is-hovered,.button.is-info:hover{background-color:#3488ce;border-color:transparent;color:#fff}.button.is-info.is-focused,.button.is-info:focus{border-color:transparent;color:#fff}.button.is-info.is-focused:not(:active),.button.is-info:focus:not(:active){box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.button.is-info.is-active,.button.is-info:active{background-color:#3082c5;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#3e8ed0;border-color:transparent;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#3e8ed0}.button.is-info.is-inverted.is-hovered,.button.is-info.is-inverted:hover{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#3e8ed0}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-info.is-outlined{background-color:transparent;border-color:#3e8ed0;color:#3e8ed0}.button.is-info.is-outlined.is-focused,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined:hover{background-color:#3e8ed0;border-color:#3e8ed0;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #3e8ed0 #3e8ed0!important}.button.is-info.is-outlined.is-loading.is-focused::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#3e8ed0;box-shadow:none;color:#3e8ed0}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined.is-focused,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined:hover{background-color:#fff;color:#3e8ed0}.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #3e8ed0 #3e8ed0!important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#eff5fb;color:#296fa8}.button.is-info.is-light.is-hovered,.button.is-info.is-light:hover{background-color:#e4eff9;border-color:transparent;color:#296fa8}.button.is-info.is-light.is-active,.button.is-info.is-light:active{background-color:#dae9f6;border-color:transparent;color:#296fa8}.button.is-success{background-color:#48c78e;border-color:transparent;color:#fff}.button.is-success.is-hovered,.button.is-success:hover{background-color:#3ec487;border-color:transparent;color:#fff}.button.is-success.is-focused,.button.is-success:focus{border-color:transparent;color:#fff}.button.is-success.is-focused:not(:active),.button.is-success:focus:not(:active){box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.button.is-success.is-active,.button.is-success:active{background-color:#3abb81;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#48c78e;border-color:transparent;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#48c78e}.button.is-success.is-inverted.is-hovered,.button.is-success.is-inverted:hover{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#48c78e}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-success.is-outlined{background-color:transparent;border-color:#48c78e;color:#48c78e}.button.is-success.is-outlined.is-focused,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined:hover{background-color:#48c78e;border-color:#48c78e;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #48c78e #48c78e!important}.button.is-success.is-outlined.is-loading.is-focused::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#48c78e;box-shadow:none;color:#48c78e}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined.is-focused,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined:hover{background-color:#fff;color:#48c78e}.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #48c78e #48c78e!important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#effaf5;color:#257953}.button.is-success.is-light.is-hovered,.button.is-success.is-light:hover{background-color:#e6f7ef;border-color:transparent;color:#257953}.button.is-success.is-light.is-active,.button.is-success.is-light:active{background-color:#dcf4e9;border-color:transparent;color:#257953}.button.is-warning{background-color:#ffe08a;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-hovered,.button.is-warning:hover{background-color:#ffdc7d;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused,.button.is-warning:focus{border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning.is-focused:not(:active),.button.is-warning:focus:not(:active){box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.button.is-warning.is-active,.button.is-warning:active{background-color:#ffd970;border-color:transparent;color:rgba(0,0,0,.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffe08a;border-color:transparent;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,.7);color:#ffe08a}.button.is-warning.is-inverted.is-hovered,.button.is-warning.is-inverted:hover{background-color:rgba(0,0,0,.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,.7);border-color:transparent;box-shadow:none;color:#ffe08a}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffe08a;color:#ffe08a}.button.is-warning.is-outlined.is-focused,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined:hover{background-color:#ffe08a;border-color:#ffe08a;color:rgba(0,0,0,.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffe08a #ffe08a!important}.button.is-warning.is-outlined.is-loading.is-focused::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading:hover::after{border-color:transparent transparent rgba(0,0,0,.7) rgba(0,0,0,.7)!important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffe08a;box-shadow:none;color:#ffe08a}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);color:rgba(0,0,0,.7)}.button.is-warning.is-inverted.is-outlined.is-focused,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined:hover{background-color:rgba(0,0,0,.7);color:#ffe08a}.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #ffe08a #ffe08a!important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,.7);box-shadow:none;color:rgba(0,0,0,.7)}.button.is-warning.is-light{background-color:#fffaeb;color:#946c00}.button.is-warning.is-light.is-hovered,.button.is-warning.is-light:hover{background-color:#fff6de;border-color:transparent;color:#946c00}.button.is-warning.is-light.is-active,.button.is-warning.is-light:active{background-color:#fff3d1;border-color:transparent;color:#946c00}.button.is-danger{background-color:#f14668;border-color:transparent;color:#fff}.button.is-danger.is-hovered,.button.is-danger:hover{background-color:#f03a5f;border-color:transparent;color:#fff}.button.is-danger.is-focused,.button.is-danger:focus{border-color:transparent;color:#fff}.button.is-danger.is-focused:not(:active),.button.is-danger:focus:not(:active){box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.button.is-danger.is-active,.button.is-danger:active{background-color:#ef2e55;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#f14668;border-color:transparent;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#f14668}.button.is-danger.is-inverted.is-hovered,.button.is-danger.is-inverted:hover{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#f14668}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff!important}.button.is-danger.is-outlined{background-color:transparent;border-color:#f14668;color:#f14668}.button.is-danger.is-outlined.is-focused,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined:hover{background-color:#f14668;border-color:#f14668;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #f14668 #f14668!important}.button.is-danger.is-outlined.is-loading.is-focused::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading:hover::after{border-color:transparent transparent #fff #fff!important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#f14668;box-shadow:none;color:#f14668}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined.is-focused,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined:hover{background-color:#fff;color:#f14668}.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading:hover::after{border-color:transparent transparent #f14668 #f14668!important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#feecf0;color:#cc0f35}.button.is-danger.is-light.is-hovered,.button.is-danger.is-light:hover{background-color:#fde0e6;border-color:transparent;color:#cc0f35}.button.is-danger.is-light.is-active,.button.is-danger.is-light:active{background-color:#fcd4dc;border-color:transparent;color:#cc0f35}.button.is-small{font-size:.75rem}.button.is-small:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent!important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * .5));top:calc(50% - (1em * .5));position:absolute!important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#7a7a7a;box-shadow:none;pointer-events:none}.button.is-rounded{border-radius:9999px;padding-left:calc(1em + .25em);padding-right:calc(1em + .25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button.is-hovered,.buttons.has-addons .button:hover{z-index:2}.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-focused,.buttons.has-addons .button.is-selected,.buttons.has-addons .button:active,.buttons.has-addons .button:focus{z-index:3}.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button.is-selected:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button:focus:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:.25rem;margin-right:.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:.25rem;margin-right:.25rem}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none!important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width:1024px){.container{max-width:960px}}@media screen and (max-width:1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width:1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width:1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width:1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:.25em}.content blockquote:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content p:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child),.content ul:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#363636;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:.8em}.content h5{font-size:1.125em;margin-bottom:.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol:not([type]).is-lower-alpha{list-style-type:lower-alpha}.content ol:not([type]).is-lower-roman{list-style-type:lower-roman}.content ol:not([type]).is-upper-alpha{list-style-type:upper-alpha}.content ol:not([type]).is-upper-roman{list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:1.25em 1.5em;white-space:pre;word-wrap:normal}.content sub,.content sup{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.content table th{color:#363636}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#363636}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#363636}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image{display:block;position:relative}.image img{display:block;height:auto;width:100%}.image img.is-rounded{border-radius:9999px}.image.is-fullwidth{width:100%}.image.is-16by9 .has-ratio,.image.is-16by9 img,.image.is-1by1 .has-ratio,.image.is-1by1 img,.image.is-1by2 .has-ratio,.image.is-1by2 img,.image.is-1by3 .has-ratio,.image.is-1by3 img,.image.is-2by1 .has-ratio,.image.is-2by1 img,.image.is-2by3 .has-ratio,.image.is-2by3 img,.image.is-3by1 .has-ratio,.image.is-3by1 img,.image.is-3by2 .has-ratio,.image.is-3by2 img,.image.is-3by4 .has-ratio,.image.is-3by4 img,.image.is-3by5 .has-ratio,.image.is-3by5 img,.image.is-4by3 .has-ratio,.image.is-4by3 img,.image.is-4by5 .has-ratio,.image.is-4by5 img,.image.is-5by3 .has-ratio,.image.is-5by3 img,.image.is-5by4 .has-ratio,.image.is-5by4 img,.image.is-9by16 .has-ratio,.image.is-9by16 img,.image.is-square .has-ratio,.image.is-square img{height:100%;width:100%}.image.is-1by1,.image.is-square{padding-top:100%}.image.is-5by4{padding-top:80%}.image.is-4by3{padding-top:75%}.image.is-3by2{padding-top:66.6666%}.image.is-5by3{padding-top:60%}.image.is-16by9{padding-top:56.25%}.image.is-2by1{padding-top:50%}.image.is-3by1{padding-top:33.3333%}.image.is-4by5{padding-top:125%}.image.is-3by4{padding-top:133.3333%}.image.is-2by3{padding-top:150%}.image.is-3by5{padding-top:166.6666%}.image.is-9by16{padding-top:177.7777%}.image.is-1by2{padding-top:200%}.image.is-1by3{padding-top:300%}.image.is-16x16{height:16px;width:16px}.image.is-24x24{height:24px;width:24px}.image.is-32x32{height:32px;width:32px}.image.is-48x48{height:48px;width:48px}.image.is-64x64{height:64px;width:64px}.image.is-96x96{height:96px;width:96px}.image.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:0 0}.notification>.delete{right:.5rem;position:absolute;top:.5rem}.notification .content,.notification .subtitle,.notification .title{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.notification.is-dark{background-color:#363636;color:#fff}.notification.is-primary{background-color:#00d1b2;color:#fff}.notification.is-primary.is-light{background-color:#ebfffc;color:#00947e}.notification.is-link{background-color:#485fc7;color:#fff}.notification.is-link.is-light{background-color:#eff1fa;color:#3850b7}.notification.is-info{background-color:#3e8ed0;color:#fff}.notification.is-info.is-light{background-color:#eff5fb;color:#296fa8}.notification.is-success{background-color:#48c78e;color:#fff}.notification.is-success.is-light{background-color:#effaf5;color:#257953}.notification.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.notification.is-warning.is-light{background-color:#fffaeb;color:#946c00}.notification.is-danger{background-color:#f14668;color:#fff}.notification.is-danger.is-light{background-color:#feecf0;color:#cc0f35}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#4a4a4a}.progress::-moz-progress-bar{background-color:#4a4a4a}.progress::-ms-fill{background-color:#4a4a4a;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right,#fff 30%,#ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right,#0a0a0a 30%,#ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right,#f5f5f5 30%,#ededed 30%)}.progress.is-dark::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate{background-image:linear-gradient(to right,#363636 30%,#ededed 30%)}.progress.is-primary::-webkit-progress-value{background-color:#00d1b2}.progress.is-primary::-moz-progress-bar{background-color:#00d1b2}.progress.is-primary::-ms-fill{background-color:#00d1b2}.progress.is-primary:indeterminate{background-image:linear-gradient(to right,#00d1b2 30%,#ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#485fc7}.progress.is-link::-moz-progress-bar{background-color:#485fc7}.progress.is-link::-ms-fill{background-color:#485fc7}.progress.is-link:indeterminate{background-image:linear-gradient(to right,#485fc7 30%,#ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#3e8ed0}.progress.is-info::-moz-progress-bar{background-color:#3e8ed0}.progress.is-info::-ms-fill{background-color:#3e8ed0}.progress.is-info:indeterminate{background-image:linear-gradient(to right,#3e8ed0 30%,#ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#48c78e}.progress.is-success::-moz-progress-bar{background-color:#48c78e}.progress.is-success::-ms-fill{background-color:#48c78e}.progress.is-success:indeterminate{background-image:linear-gradient(to right,#48c78e 30%,#ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffe08a}.progress.is-warning::-moz-progress-bar{background-color:#ffe08a}.progress.is-warning::-ms-fill{background-color:#ffe08a}.progress.is-warning:indeterminate{background-image:linear-gradient(to right,#ffe08a 30%,#ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#f14668}.progress.is-danger::-moz-progress-bar{background-color:#f14668}.progress.is-danger::-ms-fill{background-color:#f14668}.progress.is-danger:indeterminate{background-image:linear-gradient(to right,#f14668 30%,#ededed 30%)}.progress:indeterminate{-webkit-animation-duration:1.5s;animation-duration:1.5s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:moveIndeterminate;animation-name:moveIndeterminate;-webkit-animation-timing-function:linear;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right,#4a4a4a 30%,#ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@-webkit-keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#363636}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:.5em .75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#00d1b2;border-color:#00d1b2;color:#fff}.table td.is-link,.table th.is-link{background-color:#485fc7;border-color:#485fc7;color:#fff}.table td.is-info,.table th.is-info{background-color:#3e8ed0;border-color:#3e8ed0;color:#fff}.table td.is-success,.table th.is-success{background-color:#48c78e;border-color:#48c78e;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffe08a;border-color:#ffe08a;color:rgba(0,0,0,.7)}.table td.is-danger,.table th.is-danger{background-color:#f14668;border-color:#f14668;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#00d1b2;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#363636}.table th:not([align]){text-align:inherit}.table tr.is-selected{background-color:#00d1b2;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:transparent}.table thead td,.table thead th{border-width:0 0 2px;color:#363636}.table tfoot{background-color:transparent}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#363636}.table tbody{background-color:transparent}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:.25em .5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag{margin-bottom:.5rem}.tags .tag:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag{margin-right:.25rem;margin-left:.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child){margin-left:.5rem}.tags.is-right .tag:not(:last-child){margin-right:0}.tags.has-addons .tag{margin-right:0}.tags.has-addons .tag:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#4a4a4a;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:.75em;padding-right:.75em;white-space:nowrap}.tag:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag:not(body).is-white{background-color:#fff;color:#0a0a0a}.tag:not(body).is-black{background-color:#0a0a0a;color:#fff}.tag:not(body).is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.tag:not(body).is-dark{background-color:#363636;color:#fff}.tag:not(body).is-primary{background-color:#00d1b2;color:#fff}.tag:not(body).is-primary.is-light{background-color:#ebfffc;color:#00947e}.tag:not(body).is-link{background-color:#485fc7;color:#fff}.tag:not(body).is-link.is-light{background-color:#eff1fa;color:#3850b7}.tag:not(body).is-info{background-color:#3e8ed0;color:#fff}.tag:not(body).is-info.is-light{background-color:#eff5fb;color:#296fa8}.tag:not(body).is-success{background-color:#48c78e;color:#fff}.tag:not(body).is-success.is-light{background-color:#effaf5;color:#257953}.tag:not(body).is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.tag:not(body).is-warning.is-light{background-color:#fffaeb;color:#946c00}.tag:not(body).is-danger{background-color:#f14668;color:#fff}.tag:not(body).is-danger.is-light{background-color:#feecf0;color:#cc0f35}.tag:not(body).is-normal{font-size:.75rem}.tag:not(body).is-medium{font-size:1rem}.tag:not(body).is-large{font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag:not(body).is-delete{margin-left:1px;padding:0;position:relative;width:2em}.tag:not(body).is-delete::after,.tag:not(body).is-delete::before{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag:not(body).is-delete::before{height:1px;width:50%}.tag:not(body).is-delete::after{height:50%;width:1px}.tag:not(body).is-delete:focus,.tag:not(body).is-delete:hover{background-color:#e8e8e8}.tag:not(body).is-delete:active{background-color:#dbdbdb}.tag:not(body).is-rounded{border-radius:9999px}a.tag:hover{text-decoration:underline}.subtitle,.title{word-break:break-word}.subtitle em,.subtitle span,.title em,.title span{font-weight:inherit}.subtitle sub,.title sub{font-size:.75em}.subtitle sup,.title sup{font-size:.75em}.subtitle .tag,.title .tag{vertical-align:middle}.title{color:#363636;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#4a4a4a;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#363636;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:.25rem .5rem;text-align:center;vertical-align:top}.input,.select select,.textarea{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.input::-moz-placeholder,.select select::-moz-placeholder,.textarea::-moz-placeholder{color:rgba(54,54,54,.3)}.input::-webkit-input-placeholder,.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:rgba(54,54,54,.3)}.input:-moz-placeholder,.select select:-moz-placeholder,.textarea:-moz-placeholder{color:rgba(54,54,54,.3)}.input:-ms-input-placeholder,.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:rgba(54,54,54,.3)}.input:hover,.is-hovered.input,.is-hovered.textarea,.select select.is-hovered,.select select:hover,.textarea:hover{border-color:#b5b5b5}.input:active,.input:focus,.is-active.input,.is-active.textarea,.is-focused.input,.is-focused.textarea,.select select.is-active,.select select.is-focused,.select select:active,.select select:focus,.textarea:active,.textarea:focus{border-color:#485fc7;box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#7a7a7a}.input[disabled]::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder{color:rgba(122,122,122,.3)}.input[disabled]:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder{color:rgba(122,122,122,.3)}.input,.textarea{box-shadow:inset 0 .0625em .125em rgba(10,10,10,.05);max-width:100%;width:100%}.input[readonly],.textarea[readonly]{box-shadow:none}.is-white.input,.is-white.textarea{border-color:#fff}.is-white.input:active,.is-white.input:focus,.is-white.is-active.input,.is-white.is-active.textarea,.is-white.is-focused.input,.is-white.is-focused.textarea,.is-white.textarea:active,.is-white.textarea:focus{box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.is-black.input,.is-black.textarea{border-color:#0a0a0a}.is-black.input:active,.is-black.input:focus,.is-black.is-active.input,.is-black.is-active.textarea,.is-black.is-focused.input,.is-black.is-focused.textarea,.is-black.textarea:active,.is-black.textarea:focus{box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.is-light.input,.is-light.textarea{border-color:#f5f5f5}.is-light.input:active,.is-light.input:focus,.is-light.is-active.input,.is-light.is-active.textarea,.is-light.is-focused.input,.is-light.is-focused.textarea,.is-light.textarea:active,.is-light.textarea:focus{box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.is-dark.input,.is-dark.textarea{border-color:#363636}.is-dark.input:active,.is-dark.input:focus,.is-dark.is-active.input,.is-dark.is-active.textarea,.is-dark.is-focused.input,.is-dark.is-focused.textarea,.is-dark.textarea:active,.is-dark.textarea:focus{box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.is-primary.input,.is-primary.textarea{border-color:#00d1b2}.is-primary.input:active,.is-primary.input:focus,.is-primary.is-active.input,.is-primary.is-active.textarea,.is-primary.is-focused.input,.is-primary.is-focused.textarea,.is-primary.textarea:active,.is-primary.textarea:focus{box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.is-link.input,.is-link.textarea{border-color:#485fc7}.is-link.input:active,.is-link.input:focus,.is-link.is-active.input,.is-link.is-active.textarea,.is-link.is-focused.input,.is-link.is-focused.textarea,.is-link.textarea:active,.is-link.textarea:focus{box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.is-info.input,.is-info.textarea{border-color:#3e8ed0}.is-info.input:active,.is-info.input:focus,.is-info.is-active.input,.is-info.is-active.textarea,.is-info.is-focused.input,.is-info.is-focused.textarea,.is-info.textarea:active,.is-info.textarea:focus{box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.is-success.input,.is-success.textarea{border-color:#48c78e}.is-success.input:active,.is-success.input:focus,.is-success.is-active.input,.is-success.is-active.textarea,.is-success.is-focused.input,.is-success.is-focused.textarea,.is-success.textarea:active,.is-success.textarea:focus{box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.is-warning.input,.is-warning.textarea{border-color:#ffe08a}.is-warning.input:active,.is-warning.input:focus,.is-warning.is-active.input,.is-warning.is-active.textarea,.is-warning.is-focused.input,.is-warning.is-focused.textarea,.is-warning.textarea:active,.is-warning.textarea:focus{box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.is-danger.input,.is-danger.textarea{border-color:#f14668}.is-danger.input:active,.is-danger.input:focus,.is-danger.is-active.input,.is-danger.is-active.textarea,.is-danger.is-focused.input,.is-danger.is-focused.textarea,.is-danger.textarea:active,.is-danger.textarea:focus{box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.is-small.input,.is-small.textarea{border-radius:2px;font-size:.75rem}.is-medium.input,.is-medium.textarea{font-size:1.25rem}.is-large.input,.is-large.textarea{font-size:1.5rem}.is-fullwidth.input,.is-fullwidth.textarea{display:block;width:100%}.is-inline.input,.is-inline.textarea{display:inline;width:auto}.input.is-rounded{border-radius:9999px;padding-left:calc(calc(.75em - 1px) + .375em);padding-right:calc(calc(.75em - 1px) + .375em)}.input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.checkbox,.radio{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.checkbox input,.radio input{cursor:pointer}.checkbox:hover,.radio:hover{color:#363636}.checkbox input[disabled],.checkbox[disabled],.radio input[disabled],.radio[disabled],fieldset[disabled] .checkbox,fieldset[disabled] .radio{color:#7a7a7a;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#485fc7;right:1.125em;z-index:4}.select.is-rounded select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:0}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#363636}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select.is-hovered,.select.is-white select:hover{border-color:#f2f2f2}.select.is-white select.is-active,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select:focus{box-shadow:0 0 0 .125em rgba(255,255,255,.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select.is-hovered,.select.is-black select:hover{border-color:#000}.select.is-black select.is-active,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select:focus{box-shadow:0 0 0 .125em rgba(10,10,10,.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select.is-hovered,.select.is-light select:hover{border-color:#e8e8e8}.select.is-light select.is-active,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select:focus{box-shadow:0 0 0 .125em rgba(245,245,245,.25)}.select.is-dark:not(:hover)::after{border-color:#363636}.select.is-dark select{border-color:#363636}.select.is-dark select.is-hovered,.select.is-dark select:hover{border-color:#292929}.select.is-dark select.is-active,.select.is-dark select.is-focused,.select.is-dark select:active,.select.is-dark select:focus{box-shadow:0 0 0 .125em rgba(54,54,54,.25)}.select.is-primary:not(:hover)::after{border-color:#00d1b2}.select.is-primary select{border-color:#00d1b2}.select.is-primary select.is-hovered,.select.is-primary select:hover{border-color:#00b89c}.select.is-primary select.is-active,.select.is-primary select.is-focused,.select.is-primary select:active,.select.is-primary select:focus{box-shadow:0 0 0 .125em rgba(0,209,178,.25)}.select.is-link:not(:hover)::after{border-color:#485fc7}.select.is-link select{border-color:#485fc7}.select.is-link select.is-hovered,.select.is-link select:hover{border-color:#3a51bb}.select.is-link select.is-active,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select:focus{box-shadow:0 0 0 .125em rgba(72,95,199,.25)}.select.is-info:not(:hover)::after{border-color:#3e8ed0}.select.is-info select{border-color:#3e8ed0}.select.is-info select.is-hovered,.select.is-info select:hover{border-color:#3082c5}.select.is-info select.is-active,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select:focus{box-shadow:0 0 0 .125em rgba(62,142,208,.25)}.select.is-success:not(:hover)::after{border-color:#48c78e}.select.is-success select{border-color:#48c78e}.select.is-success select.is-hovered,.select.is-success select:hover{border-color:#3abb81}.select.is-success select.is-active,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select:focus{box-shadow:0 0 0 .125em rgba(72,199,142,.25)}.select.is-warning:not(:hover)::after{border-color:#ffe08a}.select.is-warning select{border-color:#ffe08a}.select.is-warning select.is-hovered,.select.is-warning select:hover{border-color:#ffd970}.select.is-warning select.is-active,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select:focus{box-shadow:0 0 0 .125em rgba(255,224,138,.25)}.select.is-danger:not(:hover)::after{border-color:#f14668}.select.is-danger select{border-color:#f14668}.select.is-danger select.is-hovered,.select.is-danger select:hover{border-color:#ef2e55}.select.is-danger select.is-active,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select:focus{box-shadow:0 0 0 .125em rgba(241,70,104,.25)}.select.is-small{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#7a7a7a}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:.625em;transform:none}.select.is-loading.is-small:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white.is-hovered .file-cta,.file.is-white:hover .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white.is-focused .file-cta,.file.is-white:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(255,255,255,.25);color:#0a0a0a}.file.is-white.is-active .file-cta,.file.is-white:active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black.is-hovered .file-cta,.file.is-black:hover .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black.is-focused .file-cta,.file.is-black:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(10,10,10,.25);color:#fff}.file.is-black.is-active .file-cta,.file.is-black:active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-light.is-hovered .file-cta,.file.is-light:hover .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-light.is-focused .file-cta,.file.is-light:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(245,245,245,.25);color:rgba(0,0,0,.7)}.file.is-light.is-active .file-cta,.file.is-light:active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-dark .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark.is-hovered .file-cta,.file.is-dark:hover .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark.is-focused .file-cta,.file.is-dark:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(54,54,54,.25);color:#fff}.file.is-dark.is-active .file-cta,.file.is-dark:active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta{background-color:#00d1b2;border-color:transparent;color:#fff}.file.is-primary.is-hovered .file-cta,.file.is-primary:hover .file-cta{background-color:#00c4a7;border-color:transparent;color:#fff}.file.is-primary.is-focused .file-cta,.file.is-primary:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(0,209,178,.25);color:#fff}.file.is-primary.is-active .file-cta,.file.is-primary:active .file-cta{background-color:#00b89c;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#485fc7;border-color:transparent;color:#fff}.file.is-link.is-hovered .file-cta,.file.is-link:hover .file-cta{background-color:#3e56c4;border-color:transparent;color:#fff}.file.is-link.is-focused .file-cta,.file.is-link:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(72,95,199,.25);color:#fff}.file.is-link.is-active .file-cta,.file.is-link:active .file-cta{background-color:#3a51bb;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#3e8ed0;border-color:transparent;color:#fff}.file.is-info.is-hovered .file-cta,.file.is-info:hover .file-cta{background-color:#3488ce;border-color:transparent;color:#fff}.file.is-info.is-focused .file-cta,.file.is-info:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(62,142,208,.25);color:#fff}.file.is-info.is-active .file-cta,.file.is-info:active .file-cta{background-color:#3082c5;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#48c78e;border-color:transparent;color:#fff}.file.is-success.is-hovered .file-cta,.file.is-success:hover .file-cta{background-color:#3ec487;border-color:transparent;color:#fff}.file.is-success.is-focused .file-cta,.file.is-success:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(72,199,142,.25);color:#fff}.file.is-success.is-active .file-cta,.file.is-success:active .file-cta{background-color:#3abb81;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffe08a;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-hovered .file-cta,.file.is-warning:hover .file-cta{background-color:#ffdc7d;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-warning.is-focused .file-cta,.file.is-warning:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(255,224,138,.25);color:rgba(0,0,0,.7)}.file.is-warning.is-active .file-cta,.file.is-warning:active .file-cta{background-color:#ffd970;border-color:transparent;color:rgba(0,0,0,.7)}.file.is-danger .file-cta{background-color:#f14668;border-color:transparent;color:#fff}.file.is-danger.is-hovered .file-cta,.file.is-danger:hover .file-cta{background-color:#f03a5f;border-color:transparent;color:#fff}.file.is-danger.is-focused .file-cta,.file.is-danger:focus .file-cta{border-color:transparent;box-shadow:0 0 .5em rgba(241,70,104,.25);color:#fff}.file.is-danger.is-active .file-cta,.file.is-danger:active .file-cta{background-color:#ef2e55;border-color:transparent;color:#fff}.file.is-small{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#363636}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#363636}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:0;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#4a4a4a}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#363636;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:.5em}.label.is-small{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark{color:#363636}.help.is-primary{color:#00d1b2}.help.is-link{color:#485fc7}.help.is-info{color:#3e8ed0}.help.is-success{color:#48c78e}.help.is-warning{color:#ffe08a}.help.is-danger{color:#f14668}.field:not(:last-child){margin-bottom:.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]).is-hovered,.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .input:not([disabled]).is-hovered,.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]).is-hovered,.field.has-addons .control .select select:not([disabled]):hover{z-index:2}.field.has-addons .control .button:not([disabled]).is-active,.field.has-addons .control .button:not([disabled]).is-focused,.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .input:not([disabled]).is-active,.field.has-addons .control .input:not([disabled]).is-focused,.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control .select select:not([disabled]).is-active,.field.has-addons .control .select select:not([disabled]).is-focused,.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select:not([disabled]):focus{z-index:3}.field.has-addons .control .button:not([disabled]).is-active:hover,.field.has-addons .control .button:not([disabled]).is-focused:hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .input:not([disabled]).is-active:hover,.field.has-addons .control .input:not([disabled]).is-focused:hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control .select select:not([disabled]).is-active:hover,.field.has-addons .control .select select:not([disabled]).is-focused:hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select:not([disabled]):focus:hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width:769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width:768px){.field-label{margin-bottom:.5rem}}@media screen and (min-width:769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small{font-size:.75rem;padding-top:.375em}.field-label.is-normal{padding-top:.375em}.field-label.is-medium{font-size:1.25rem;padding-top:.375em}.field-label.is-large{font-size:1.5rem;padding-top:.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width:769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#4a4a4a}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute!important;right:.625em;top:.625em;z-index:4}.control.is-loading.is-small:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#485fc7;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#363636;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ol,.breadcrumb ul{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);color:#4a4a4a;max-width:100%;position:relative}.card-content:first-child,.card-footer:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-content:last-child,.card-footer:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:transparent;align-items:stretch;box-shadow:0 .125em .25em rgba(10,10,10,.1);display:flex}.card-header-title{align-items:center;color:#363636;display:flex;flex-grow:1;font-weight:700;padding:.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:0 0;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:transparent;padding:1.5rem}.card-footer{background-color:transparent;border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:.875rem;line-height:1.5;padding:.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#485fc7;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width:769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .subtitle,.level-item .title{margin-bottom:0}@media screen and (max-width:768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width:769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width:768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width:769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width:769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width:768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#4a4a4a;display:block;padding:.5em .75em}.menu-list a:hover{background-color:#f5f5f5;color:#363636}.menu-list a.is-active{background-color:#485fc7;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#7a7a7a;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark{background-color:#fafafa}.message.is-dark .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body{border-color:#363636}.message.is-primary{background-color:#ebfffc}.message.is-primary .message-header{background-color:#00d1b2;color:#fff}.message.is-primary .message-body{border-color:#00d1b2;color:#00947e}.message.is-link{background-color:#eff1fa}.message.is-link .message-header{background-color:#485fc7;color:#fff}.message.is-link .message-body{border-color:#485fc7;color:#3850b7}.message.is-info{background-color:#eff5fb}.message.is-info .message-header{background-color:#3e8ed0;color:#fff}.message.is-info .message-body{border-color:#3e8ed0;color:#296fa8}.message.is-success{background-color:#effaf5}.message.is-success .message-header{background-color:#48c78e;color:#fff}.message.is-success .message-body{border-color:#48c78e;color:#257953}.message.is-warning{background-color:#fffaeb}.message.is-warning .message-header{background-color:#ffe08a;color:rgba(0,0,0,.7)}.message.is-warning .message-body{border-color:#ffe08a;color:#946c00}.message.is-danger{background-color:#feecf0}.message.is-danger .message-header{background-color:#f14668;color:#fff}.message.is-danger .message-body{border-color:#f14668;color:#cc0f35}.message-header{align-items:center;background-color:#4a4a4a;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#4a4a4a;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:transparent}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,.86)}.modal-card,.modal-content{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width:769px){.modal-card,.modal-content{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:0 0;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-foot,.modal-card-head{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#363636;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link,.navbar.is-white .navbar-brand>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width:1024px){.navbar.is-white .navbar-end .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-start>.navbar-item{color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-end .navbar-link::after,.navbar.is-white .navbar-start .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand .navbar-link,.navbar.is-black .navbar-brand>.navbar-item{color:#fff}.navbar.is-black .navbar-brand .navbar-link.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-black .navbar-end .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-start>.navbar-item{color:#fff}.navbar.is-black .navbar-end .navbar-link.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover{background-color:#000;color:#fff}.navbar.is-black .navbar-end .navbar-link::after,.navbar.is-black .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link,.navbar.is-light .navbar-brand>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,.7)}@media screen and (min-width:1024px){.navbar.is-light .navbar-end .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-start>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-light .navbar-end .navbar-link.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-end .navbar-link::after,.navbar.is-light .navbar-start .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,.7)}}.navbar.is-dark{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand .navbar-link,.navbar.is-dark .navbar-brand>.navbar-item{color:#fff}.navbar.is-dark .navbar-brand .navbar-link.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-dark .navbar-end .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.navbar.is-dark .navbar-start>.navbar-item{color:#fff}.navbar.is-dark .navbar-end .navbar-link.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover{background-color:#292929;color:#fff}.navbar.is-dark .navbar-end .navbar-link::after,.navbar.is-dark .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary{background-color:#00d1b2;color:#fff}.navbar.is-primary .navbar-brand .navbar-link,.navbar.is-primary .navbar-brand>.navbar-item{color:#fff}.navbar.is-primary .navbar-brand .navbar-link.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-primary .navbar-end .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.navbar.is-primary .navbar-start>.navbar-item{color:#fff}.navbar.is-primary .navbar-end .navbar-link.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-end .navbar-link::after,.navbar.is-primary .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link{background-color:#00b89c;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active{background-color:#00d1b2;color:#fff}}.navbar.is-link{background-color:#485fc7;color:#fff}.navbar.is-link .navbar-brand .navbar-link,.navbar.is-link .navbar-brand>.navbar-item{color:#fff}.navbar.is-link .navbar-brand .navbar-link.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-link .navbar-end .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-start>.navbar-item{color:#fff}.navbar.is-link .navbar-end .navbar-link.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-end .navbar-link::after,.navbar.is-link .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link{background-color:#3a51bb;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#485fc7;color:#fff}}.navbar.is-info{background-color:#3e8ed0;color:#fff}.navbar.is-info .navbar-brand .navbar-link,.navbar.is-info .navbar-brand>.navbar-item{color:#fff}.navbar.is-info .navbar-brand .navbar-link.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-info .navbar-end .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-start>.navbar-item{color:#fff}.navbar.is-info .navbar-end .navbar-link.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-end .navbar-link::after,.navbar.is-info .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link{background-color:#3082c5;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#3e8ed0;color:#fff}}.navbar.is-success{background-color:#48c78e;color:#fff}.navbar.is-success .navbar-brand .navbar-link,.navbar.is-success .navbar-brand>.navbar-item{color:#fff}.navbar.is-success .navbar-brand .navbar-link.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-success .navbar-end .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-start>.navbar-item{color:#fff}.navbar.is-success .navbar-end .navbar-link.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-end .navbar-link::after,.navbar.is-success .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link{background-color:#3abb81;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#48c78e;color:#fff}}.navbar.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link,.navbar.is-warning .navbar-brand>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,.7)}@media screen and (min-width:1024px){.navbar.is-warning .navbar-end .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-start>.navbar-item{color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-end .navbar-link::after,.navbar.is-warning .navbar-start .navbar-link::after{border-color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link{background-color:#ffd970;color:rgba(0,0,0,.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffe08a;color:rgba(0,0,0,.7)}}.navbar.is-danger{background-color:#f14668;color:#fff}.navbar.is-danger .navbar-brand .navbar-link,.navbar.is-danger .navbar-brand>.navbar-item{color:#fff}.navbar.is-danger .navbar-brand .navbar-link.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width:1024px){.navbar.is-danger .navbar-end .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-start>.navbar-item{color:#fff}.navbar.is-danger .navbar-end .navbar-link.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-end .navbar-link::after,.navbar.is-danger .navbar-start .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link{background-color:#ef2e55;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#f14668;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}body.has-navbar-fixed-top,html.has-navbar-fixed-top{padding-top:3.25rem}body.has-navbar-fixed-bottom,html.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#4a4a4a;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color,opacity,transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#4a4a4a;display:block;line-height:1.5;padding:.5rem .75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-.25rem;margin-right:-.25rem}.navbar-link,a.navbar-item{cursor:pointer}.navbar-link.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,a.navbar-item.is-active,a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover{background-color:#fafafa;color:#485fc7}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:transparent;border-bottom-color:#485fc7}.navbar-item.is-tab.is-active{background-color:transparent;border-bottom-color:#485fc7;border-bottom-style:solid;border-bottom-width:3px;color:#485fc7;padding-bottom:calc(.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#485fc7;margin-top:-.375em;right:1.125em}.navbar-dropdown{font-size:.875rem;padding-bottom:.5rem;padding-top:.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:.5rem 0}@media screen and (max-width:1023px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,.1);padding:.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}body.has-navbar-fixed-top-touch,html.has-navbar-fixed-top-touch{padding-top:3.25rem}body.has-navbar-fixed-bottom-touch,html.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width:1024px){.navbar,.navbar-end,.navbar-menu,.navbar-start{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-end,.navbar.is-spaced .navbar-start{align-items:center}.navbar.is-spaced .navbar-link,.navbar.is-spaced a.navbar-item{border-radius:4px}.navbar.is-transparent .navbar-link.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover{background-color:transparent!important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent!important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#485fc7}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(.25em,-.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,.1);display:none;font-size:.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#485fc7}.navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-dropdown{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity,transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.container>.navbar .navbar-brand,.navbar>.container .navbar-brand{margin-left:-.75rem}.container>.navbar .navbar-menu,.navbar>.container .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,.1)}.navbar.is-fixed-top-desktop{top:0}body.has-navbar-fixed-top-desktop,html.has-navbar-fixed-top-desktop{padding-top:3.25rem}body.has-navbar-fixed-bottom-desktop,html.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}body.has-spaced-navbar-fixed-top,html.has-spaced-navbar-fixed-top{padding-top:5.25rem}body.has-spaced-navbar-fixed-bottom,html.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}.navbar-link.is-active,a.navbar-item.is-active{color:#0a0a0a}.navbar-link.is-active:not(:focus):not(:hover),a.navbar-item.is-active:not(:focus):not(:hover){background-color:transparent}.navbar-item.has-dropdown.is-active .navbar-link,.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-next,.pagination.is-rounded .pagination-previous{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-link,.pagination-next,.pagination-previous{border-color:#dbdbdb;color:#363636;min-width:2.5em}.pagination-link:hover,.pagination-next:hover,.pagination-previous:hover{border-color:#b5b5b5;color:#363636}.pagination-link:focus,.pagination-next:focus,.pagination-previous:focus{border-color:#485fc7}.pagination-link:active,.pagination-next:active,.pagination-previous:active{box-shadow:inset 0 1px 2px rgba(10,10,10,.2)}.pagination-link[disabled],.pagination-next[disabled],.pagination-previous[disabled]{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#7a7a7a;opacity:.5}.pagination-next,.pagination-previous{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#485fc7;border-color:#485fc7;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width:768px){.pagination{flex-wrap:wrap}.pagination-next,.pagination-previous{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width:769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-ellipsis,.pagination-link,.pagination-next,.pagination-previous{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:0 .5em 1em -.125em rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.02);font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading{background-color:#00d1b2;color:#fff}.panel.is-primary .panel-tabs a.is-active{border-bottom-color:#00d1b2}.panel.is-primary .panel-block.is-active .panel-icon{color:#00d1b2}.panel.is-link .panel-heading{background-color:#485fc7;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#485fc7}.panel.is-link .panel-block.is-active .panel-icon{color:#485fc7}.panel.is-info .panel-heading{background-color:#3e8ed0;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#3e8ed0}.panel.is-info .panel-block.is-active .panel-icon{color:#3e8ed0}.panel.is-success .panel-heading{background-color:#48c78e;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#48c78e}.panel.is-success .panel-block.is-active .panel-icon{color:#48c78e}.panel.is-warning .panel-heading{background-color:#ffe08a;color:rgba(0,0,0,.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffe08a}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffe08a}.panel.is-danger .panel-heading{background-color:#f14668;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#f14668}.panel.is-danger .panel-block.is-active .panel-icon{color:#f14668}.panel-block:not(:last-child),.panel-tabs:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#363636;font-size:1.25em;font-weight:700;line-height:1.25;padding:.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#4a4a4a}.panel-list a:hover{color:#485fc7}.panel-block{align-items:center;color:#363636;display:flex;justify-content:flex-start;padding:.5em .75em}.panel-block input[type=checkbox]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#485fc7;color:#363636}.panel-block.is-active .panel-icon{color:#485fc7}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#7a7a7a;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#4a4a4a;display:flex;justify-content:center;margin-bottom:-1px;padding:.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#363636;color:#363636}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#485fc7;color:#485fc7}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:.75em;padding-right:.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:transparent!important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#485fc7;border-color:#485fc7;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0}.columns.is-mobile>.column.is-1{flex:none;width:8.33333%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333%}.columns.is-mobile>.column.is-2{flex:none;width:16.66667%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66667%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333%}.columns.is-mobile>.column.is-5{flex:none;width:41.66667%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66667%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333%}.columns.is-mobile>.column.is-8{flex:none;width:66.66667%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66667%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333%}.columns.is-mobile>.column.is-11{flex:none;width:91.66667%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66667%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width:768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0}.column.is-1-mobile{flex:none;width:8.33333%}.column.is-offset-1-mobile{margin-left:8.33333%}.column.is-2-mobile{flex:none;width:16.66667%}.column.is-offset-2-mobile{margin-left:16.66667%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333%}.column.is-offset-4-mobile{margin-left:33.33333%}.column.is-5-mobile{flex:none;width:41.66667%}.column.is-offset-5-mobile{margin-left:41.66667%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333%}.column.is-offset-7-mobile{margin-left:58.33333%}.column.is-8-mobile{flex:none;width:66.66667%}.column.is-offset-8-mobile{margin-left:66.66667%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333%}.column.is-offset-10-mobile{margin-left:83.33333%}.column.is-11-mobile{flex:none;width:91.66667%}.column.is-offset-11-mobile{margin-left:91.66667%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width:769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66667%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66667%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66667%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66667%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66667%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66667%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66667%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66667%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width:1023px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0}.column.is-1-touch{flex:none;width:8.33333%}.column.is-offset-1-touch{margin-left:8.33333%}.column.is-2-touch{flex:none;width:16.66667%}.column.is-offset-2-touch{margin-left:16.66667%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333%}.column.is-offset-4-touch{margin-left:33.33333%}.column.is-5-touch{flex:none;width:41.66667%}.column.is-offset-5-touch{margin-left:41.66667%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333%}.column.is-offset-7-touch{margin-left:58.33333%}.column.is-8-touch{flex:none;width:66.66667%}.column.is-offset-8-touch{margin-left:66.66667%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333%}.column.is-offset-10-touch{margin-left:83.33333%}.column.is-11-touch{flex:none;width:91.66667%}.column.is-offset-11-touch{margin-left:91.66667%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width:1024px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0}.column.is-1-desktop{flex:none;width:8.33333%}.column.is-offset-1-desktop{margin-left:8.33333%}.column.is-2-desktop{flex:none;width:16.66667%}.column.is-offset-2-desktop{margin-left:16.66667%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333%}.column.is-offset-4-desktop{margin-left:33.33333%}.column.is-5-desktop{flex:none;width:41.66667%}.column.is-offset-5-desktop{margin-left:41.66667%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333%}.column.is-offset-7-desktop{margin-left:58.33333%}.column.is-8-desktop{flex:none;width:66.66667%}.column.is-offset-8-desktop{margin-left:66.66667%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333%}.column.is-offset-10-desktop{margin-left:83.33333%}.column.is-11-desktop{flex:none;width:91.66667%}.column.is-offset-11-desktop{margin-left:91.66667%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width:1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0}.column.is-1-widescreen{flex:none;width:8.33333%}.column.is-offset-1-widescreen{margin-left:8.33333%}.column.is-2-widescreen{flex:none;width:16.66667%}.column.is-offset-2-widescreen{margin-left:16.66667%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333%}.column.is-offset-4-widescreen{margin-left:33.33333%}.column.is-5-widescreen{flex:none;width:41.66667%}.column.is-offset-5-widescreen{margin-left:41.66667%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333%}.column.is-offset-7-widescreen{margin-left:58.33333%}.column.is-8-widescreen{flex:none;width:66.66667%}.column.is-offset-8-widescreen{margin-left:66.66667%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333%}.column.is-offset-10-widescreen{margin-left:83.33333%}.column.is-11-widescreen{flex:none;width:91.66667%}.column.is-offset-11-widescreen{margin-left:91.66667%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width:1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0}.column.is-1-fullhd{flex:none;width:8.33333%}.column.is-offset-1-fullhd{margin-left:8.33333%}.column.is-2-fullhd{flex:none;width:16.66667%}.column.is-offset-2-fullhd{margin-left:16.66667%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333%}.column.is-offset-4-fullhd{margin-left:33.33333%}.column.is-5-fullhd{flex:none;width:41.66667%}.column.is-offset-5-fullhd{margin-left:41.66667%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333%}.column.is-offset-7-fullhd{margin-left:58.33333%}.column.is-8-fullhd{flex:none;width:66.66667%}.column.is-offset-8-fullhd{margin-left:66.66667%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333%}.column.is-offset-10-fullhd{margin-left:83.33333%}.column.is-11-fullhd{flex:none;width:91.66667%}.column.is-offset-11-fullhd{margin-left:91.66667%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0!important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width:769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width:1024px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap:0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap:0rem}@media screen and (max-width:768px){.columns.is-variable.is-0-mobile{--columnGap:0rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-0-tablet{--columnGap:0rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-0-tablet-only{--columnGap:0rem}}@media screen and (max-width:1023px){.columns.is-variable.is-0-touch{--columnGap:0rem}}@media screen and (min-width:1024px){.columns.is-variable.is-0-desktop{--columnGap:0rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-0-desktop-only{--columnGap:0rem}}@media screen and (min-width:1216px){.columns.is-variable.is-0-widescreen{--columnGap:0rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-0-widescreen-only{--columnGap:0rem}}@media screen and (min-width:1408px){.columns.is-variable.is-0-fullhd{--columnGap:0rem}}.columns.is-variable.is-1{--columnGap:0.25rem}@media screen and (max-width:768px){.columns.is-variable.is-1-mobile{--columnGap:0.25rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-1-tablet{--columnGap:0.25rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-1-tablet-only{--columnGap:0.25rem}}@media screen and (max-width:1023px){.columns.is-variable.is-1-touch{--columnGap:0.25rem}}@media screen and (min-width:1024px){.columns.is-variable.is-1-desktop{--columnGap:0.25rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-1-desktop-only{--columnGap:0.25rem}}@media screen and (min-width:1216px){.columns.is-variable.is-1-widescreen{--columnGap:0.25rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-1-widescreen-only{--columnGap:0.25rem}}@media screen and (min-width:1408px){.columns.is-variable.is-1-fullhd{--columnGap:0.25rem}}.columns.is-variable.is-2{--columnGap:0.5rem}@media screen and (max-width:768px){.columns.is-variable.is-2-mobile{--columnGap:0.5rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-2-tablet{--columnGap:0.5rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-2-tablet-only{--columnGap:0.5rem}}@media screen and (max-width:1023px){.columns.is-variable.is-2-touch{--columnGap:0.5rem}}@media screen and (min-width:1024px){.columns.is-variable.is-2-desktop{--columnGap:0.5rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-2-desktop-only{--columnGap:0.5rem}}@media screen and (min-width:1216px){.columns.is-variable.is-2-widescreen{--columnGap:0.5rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-2-widescreen-only{--columnGap:0.5rem}}@media screen and (min-width:1408px){.columns.is-variable.is-2-fullhd{--columnGap:0.5rem}}.columns.is-variable.is-3{--columnGap:0.75rem}@media screen and (max-width:768px){.columns.is-variable.is-3-mobile{--columnGap:0.75rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-3-tablet{--columnGap:0.75rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-3-tablet-only{--columnGap:0.75rem}}@media screen and (max-width:1023px){.columns.is-variable.is-3-touch{--columnGap:0.75rem}}@media screen and (min-width:1024px){.columns.is-variable.is-3-desktop{--columnGap:0.75rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-3-desktop-only{--columnGap:0.75rem}}@media screen and (min-width:1216px){.columns.is-variable.is-3-widescreen{--columnGap:0.75rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-3-widescreen-only{--columnGap:0.75rem}}@media screen and (min-width:1408px){.columns.is-variable.is-3-fullhd{--columnGap:0.75rem}}.columns.is-variable.is-4{--columnGap:1rem}@media screen and (max-width:768px){.columns.is-variable.is-4-mobile{--columnGap:1rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-4-tablet{--columnGap:1rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-4-tablet-only{--columnGap:1rem}}@media screen and (max-width:1023px){.columns.is-variable.is-4-touch{--columnGap:1rem}}@media screen and (min-width:1024px){.columns.is-variable.is-4-desktop{--columnGap:1rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-4-desktop-only{--columnGap:1rem}}@media screen and (min-width:1216px){.columns.is-variable.is-4-widescreen{--columnGap:1rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-4-widescreen-only{--columnGap:1rem}}@media screen and (min-width:1408px){.columns.is-variable.is-4-fullhd{--columnGap:1rem}}.columns.is-variable.is-5{--columnGap:1.25rem}@media screen and (max-width:768px){.columns.is-variable.is-5-mobile{--columnGap:1.25rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-5-tablet{--columnGap:1.25rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-5-tablet-only{--columnGap:1.25rem}}@media screen and (max-width:1023px){.columns.is-variable.is-5-touch{--columnGap:1.25rem}}@media screen and (min-width:1024px){.columns.is-variable.is-5-desktop{--columnGap:1.25rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-5-desktop-only{--columnGap:1.25rem}}@media screen and (min-width:1216px){.columns.is-variable.is-5-widescreen{--columnGap:1.25rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-5-widescreen-only{--columnGap:1.25rem}}@media screen and (min-width:1408px){.columns.is-variable.is-5-fullhd{--columnGap:1.25rem}}.columns.is-variable.is-6{--columnGap:1.5rem}@media screen and (max-width:768px){.columns.is-variable.is-6-mobile{--columnGap:1.5rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-6-tablet{--columnGap:1.5rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-6-tablet-only{--columnGap:1.5rem}}@media screen and (max-width:1023px){.columns.is-variable.is-6-touch{--columnGap:1.5rem}}@media screen and (min-width:1024px){.columns.is-variable.is-6-desktop{--columnGap:1.5rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-6-desktop-only{--columnGap:1.5rem}}@media screen and (min-width:1216px){.columns.is-variable.is-6-widescreen{--columnGap:1.5rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-6-widescreen-only{--columnGap:1.5rem}}@media screen and (min-width:1408px){.columns.is-variable.is-6-fullhd{--columnGap:1.5rem}}.columns.is-variable.is-7{--columnGap:1.75rem}@media screen and (max-width:768px){.columns.is-variable.is-7-mobile{--columnGap:1.75rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-7-tablet{--columnGap:1.75rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-7-tablet-only{--columnGap:1.75rem}}@media screen and (max-width:1023px){.columns.is-variable.is-7-touch{--columnGap:1.75rem}}@media screen and (min-width:1024px){.columns.is-variable.is-7-desktop{--columnGap:1.75rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-7-desktop-only{--columnGap:1.75rem}}@media screen and (min-width:1216px){.columns.is-variable.is-7-widescreen{--columnGap:1.75rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-7-widescreen-only{--columnGap:1.75rem}}@media screen and (min-width:1408px){.columns.is-variable.is-7-fullhd{--columnGap:1.75rem}}.columns.is-variable.is-8{--columnGap:2rem}@media screen and (max-width:768px){.columns.is-variable.is-8-mobile{--columnGap:2rem}}@media screen and (min-width:769px),print{.columns.is-variable.is-8-tablet{--columnGap:2rem}}@media screen and (min-width:769px) and (max-width:1023px){.columns.is-variable.is-8-tablet-only{--columnGap:2rem}}@media screen and (max-width:1023px){.columns.is-variable.is-8-touch{--columnGap:2rem}}@media screen and (min-width:1024px){.columns.is-variable.is-8-desktop{--columnGap:2rem}}@media screen and (min-width:1024px) and (max-width:1215px){.columns.is-variable.is-8-desktop-only{--columnGap:2rem}}@media screen and (min-width:1216px){.columns.is-variable.is-8-widescreen{--columnGap:2rem}}@media screen and (min-width:1216px) and (max-width:1407px){.columns.is-variable.is-8-widescreen-only{--columnGap:2rem}}@media screen and (min-width:1408px){.columns.is-variable.is-8-fullhd{--columnGap:2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0!important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem!important}@media screen and (min-width:769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333%}.tile.is-2{flex:none;width:16.66667%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333%}.tile.is-5{flex:none;width:41.66667%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333%}.tile.is-8{flex:none;width:66.66667%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333%}.tile.is-11{flex:none;width:91.66667%}.tile.is-12{flex:none;width:100%}}.has-text-white{color:#fff!important}a.has-text-white:focus,a.has-text-white:hover{color:#e6e6e6!important}.has-background-white{background-color:#fff!important}.has-text-black{color:#0a0a0a!important}a.has-text-black:focus,a.has-text-black:hover{color:#000!important}.has-background-black{background-color:#0a0a0a!important}.has-text-light{color:#f5f5f5!important}a.has-text-light:focus,a.has-text-light:hover{color:#dbdbdb!important}.has-background-light{background-color:#f5f5f5!important}.has-text-dark{color:#363636!important}a.has-text-dark:focus,a.has-text-dark:hover{color:#1c1c1c!important}.has-background-dark{background-color:#363636!important}.has-text-primary{color:#00d1b2!important}a.has-text-primary:focus,a.has-text-primary:hover{color:#009e86!important}.has-background-primary{background-color:#00d1b2!important}.has-text-primary-light{color:#ebfffc!important}a.has-text-primary-light:focus,a.has-text-primary-light:hover{color:#b8fff4!important}.has-background-primary-light{background-color:#ebfffc!important}.has-text-primary-dark{color:#00947e!important}a.has-text-primary-dark:focus,a.has-text-primary-dark:hover{color:#00c7a9!important}.has-background-primary-dark{background-color:#00947e!important}.has-text-link{color:#485fc7!important}a.has-text-link:focus,a.has-text-link:hover{color:#3449a8!important}.has-background-link{background-color:#485fc7!important}.has-text-link-light{color:#eff1fa!important}a.has-text-link-light:focus,a.has-text-link-light:hover{color:#c8cfee!important}.has-background-link-light{background-color:#eff1fa!important}.has-text-link-dark{color:#3850b7!important}a.has-text-link-dark:focus,a.has-text-link-dark:hover{color:#576dcb!important}.has-background-link-dark{background-color:#3850b7!important}.has-text-info{color:#3e8ed0!important}a.has-text-info:focus,a.has-text-info:hover{color:#2b74b1!important}.has-background-info{background-color:#3e8ed0!important}.has-text-info-light{color:#eff5fb!important}a.has-text-info-light:focus,a.has-text-info-light:hover{color:#c6ddf1!important}.has-background-info-light{background-color:#eff5fb!important}.has-text-info-dark{color:#296fa8!important}a.has-text-info-dark:focus,a.has-text-info-dark:hover{color:#368ace!important}.has-background-info-dark{background-color:#296fa8!important}.has-text-success{color:#48c78e!important}a.has-text-success:focus,a.has-text-success:hover{color:#34a873!important}.has-background-success{background-color:#48c78e!important}.has-text-success-light{color:#effaf5!important}a.has-text-success-light:focus,a.has-text-success-light:hover{color:#c8eedd!important}.has-background-success-light{background-color:#effaf5!important}.has-text-success-dark{color:#257953!important}a.has-text-success-dark:focus,a.has-text-success-dark:hover{color:#31a06e!important}.has-background-success-dark{background-color:#257953!important}.has-text-warning{color:#ffe08a!important}a.has-text-warning:focus,a.has-text-warning:hover{color:#ffd257!important}.has-background-warning{background-color:#ffe08a!important}.has-text-warning-light{color:#fffaeb!important}a.has-text-warning-light:focus,a.has-text-warning-light:hover{color:#ffecb8!important}.has-background-warning-light{background-color:#fffaeb!important}.has-text-warning-dark{color:#946c00!important}a.has-text-warning-dark:focus,a.has-text-warning-dark:hover{color:#c79200!important}.has-background-warning-dark{background-color:#946c00!important}.has-text-danger{color:#f14668!important}a.has-text-danger:focus,a.has-text-danger:hover{color:#ee1742!important}.has-background-danger{background-color:#f14668!important}.has-text-danger-light{color:#feecf0!important}a.has-text-danger-light:focus,a.has-text-danger-light:hover{color:#fabdc9!important}.has-background-danger-light{background-color:#feecf0!important}.has-text-danger-dark{color:#cc0f35!important}a.has-text-danger-dark:focus,a.has-text-danger-dark:hover{color:#ee2049!important}.has-background-danger-dark{background-color:#cc0f35!important}.has-text-black-bis{color:#121212!important}.has-background-black-bis{background-color:#121212!important}.has-text-black-ter{color:#242424!important}.has-background-black-ter{background-color:#242424!important}.has-text-grey-darker{color:#363636!important}.has-background-grey-darker{background-color:#363636!important}.has-text-grey-dark{color:#4a4a4a!important}.has-background-grey-dark{background-color:#4a4a4a!important}.has-text-grey{color:#7a7a7a!important}.has-background-grey{background-color:#7a7a7a!important}.has-text-grey-light{color:#b5b5b5!important}.has-background-grey-light{background-color:#b5b5b5!important}.has-text-grey-lighter{color:#dbdbdb!important}.has-background-grey-lighter{background-color:#dbdbdb!important}.has-text-white-ter{color:#f5f5f5!important}.has-background-white-ter{background-color:#f5f5f5!important}.has-text-white-bis{color:#fafafa!important}.has-background-white-bis{background-color:#fafafa!important}.is-flex-direction-row{flex-direction:row!important}.is-flex-direction-row-reverse{flex-direction:row-reverse!important}.is-flex-direction-column{flex-direction:column!important}.is-flex-direction-column-reverse{flex-direction:column-reverse!important}.is-flex-wrap-nowrap{flex-wrap:nowrap!important}.is-flex-wrap-wrap{flex-wrap:wrap!important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse!important}.is-justify-content-flex-start{justify-content:flex-start!important}.is-justify-content-flex-end{justify-content:flex-end!important}.is-justify-content-center{justify-content:center!important}.is-justify-content-space-between{justify-content:space-between!important}.is-justify-content-space-around{justify-content:space-around!important}.is-justify-content-space-evenly{justify-content:space-evenly!important}.is-justify-content-start{justify-content:start!important}.is-justify-content-end{justify-content:end!important}.is-justify-content-left{justify-content:left!important}.is-justify-content-right{justify-content:right!important}.is-align-content-flex-start{align-content:flex-start!important}.is-align-content-flex-end{align-content:flex-end!important}.is-align-content-center{align-content:center!important}.is-align-content-space-between{align-content:space-between!important}.is-align-content-space-around{align-content:space-around!important}.is-align-content-space-evenly{align-content:space-evenly!important}.is-align-content-stretch{align-content:stretch!important}.is-align-content-start{align-content:start!important}.is-align-content-end{align-content:end!important}.is-align-content-baseline{align-content:baseline!important}.is-align-items-stretch{align-items:stretch!important}.is-align-items-flex-start{align-items:flex-start!important}.is-align-items-flex-end{align-items:flex-end!important}.is-align-items-center{align-items:center!important}.is-align-items-baseline{align-items:baseline!important}.is-align-items-start{align-items:start!important}.is-align-items-end{align-items:end!important}.is-align-items-self-start{align-items:self-start!important}.is-align-items-self-end{align-items:self-end!important}.is-align-self-auto{align-self:auto!important}.is-align-self-flex-start{align-self:flex-start!important}.is-align-self-flex-end{align-self:flex-end!important}.is-align-self-center{align-self:center!important}.is-align-self-baseline{align-self:baseline!important}.is-align-self-stretch{align-self:stretch!important}.is-flex-grow-0{flex-grow:0!important}.is-flex-grow-1{flex-grow:1!important}.is-flex-grow-2{flex-grow:2!important}.is-flex-grow-3{flex-grow:3!important}.is-flex-grow-4{flex-grow:4!important}.is-flex-grow-5{flex-grow:5!important}.is-flex-shrink-0{flex-shrink:0!important}.is-flex-shrink-1{flex-shrink:1!important}.is-flex-shrink-2{flex-shrink:2!important}.is-flex-shrink-3{flex-shrink:3!important}.is-flex-shrink-4{flex-shrink:4!important}.is-flex-shrink-5{flex-shrink:5!important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left!important}.is-pulled-right{float:right!important}.is-radiusless{border-radius:0!important}.is-shadowless{box-shadow:none!important}.is-clickable{cursor:pointer!important;pointer-events:all!important}.is-clipped{overflow:hidden!important}.is-relative{position:relative!important}.is-marginless{margin:0!important}.is-paddingless{padding:0!important}.m-0{margin:0!important}.mt-0{margin-top:0!important}.mr-0{margin-right:0!important}.mb-0{margin-bottom:0!important}.ml-0{margin-left:0!important}.mx-0{margin-left:0!important;margin-right:0!important}.my-0{margin-top:0!important;margin-bottom:0!important}.m-1{margin:.25rem!important}.mt-1{margin-top:.25rem!important}.mr-1{margin-right:.25rem!important}.mb-1{margin-bottom:.25rem!important}.ml-1{margin-left:.25rem!important}.mx-1{margin-left:.25rem!important;margin-right:.25rem!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.m-2{margin:.5rem!important}.mt-2{margin-top:.5rem!important}.mr-2{margin-right:.5rem!important}.mb-2{margin-bottom:.5rem!important}.ml-2{margin-left:.5rem!important}.mx-2{margin-left:.5rem!important;margin-right:.5rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.m-3{margin:.75rem!important}.mt-3{margin-top:.75rem!important}.mr-3{margin-right:.75rem!important}.mb-3{margin-bottom:.75rem!important}.ml-3{margin-left:.75rem!important}.mx-3{margin-left:.75rem!important;margin-right:.75rem!important}.my-3{margin-top:.75rem!important;margin-bottom:.75rem!important}.m-4{margin:1rem!important}.mt-4{margin-top:1rem!important}.mr-4{margin-right:1rem!important}.mb-4{margin-bottom:1rem!important}.ml-4{margin-left:1rem!important}.mx-4{margin-left:1rem!important;margin-right:1rem!important}.my-4{margin-top:1rem!important;margin-bottom:1rem!important}.m-5{margin:1.5rem!important}.mt-5{margin-top:1.5rem!important}.mr-5{margin-right:1.5rem!important}.mb-5{margin-bottom:1.5rem!important}.ml-5{margin-left:1.5rem!important}.mx-5{margin-left:1.5rem!important;margin-right:1.5rem!important}.my-5{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.m-6{margin:3rem!important}.mt-6{margin-top:3rem!important}.mr-6{margin-right:3rem!important}.mb-6{margin-bottom:3rem!important}.ml-6{margin-left:3rem!important}.mx-6{margin-left:3rem!important;margin-right:3rem!important}.my-6{margin-top:3rem!important;margin-bottom:3rem!important}.m-auto{margin:auto!important}.mt-auto{margin-top:auto!important}.mr-auto{margin-right:auto!important}.mb-auto{margin-bottom:auto!important}.ml-auto{margin-left:auto!important}.mx-auto{margin-left:auto!important;margin-right:auto!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.p-0{padding:0!important}.pt-0{padding-top:0!important}.pr-0{padding-right:0!important}.pb-0{padding-bottom:0!important}.pl-0{padding-left:0!important}.px-0{padding-left:0!important;padding-right:0!important}.py-0{padding-top:0!important;padding-bottom:0!important}.p-1{padding:.25rem!important}.pt-1{padding-top:.25rem!important}.pr-1{padding-right:.25rem!important}.pb-1{padding-bottom:.25rem!important}.pl-1{padding-left:.25rem!important}.px-1{padding-left:.25rem!important;padding-right:.25rem!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.p-2{padding:.5rem!important}.pt-2{padding-top:.5rem!important}.pr-2{padding-right:.5rem!important}.pb-2{padding-bottom:.5rem!important}.pl-2{padding-left:.5rem!important}.px-2{padding-left:.5rem!important;padding-right:.5rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.p-3{padding:.75rem!important}.pt-3{padding-top:.75rem!important}.pr-3{padding-right:.75rem!important}.pb-3{padding-bottom:.75rem!important}.pl-3{padding-left:.75rem!important}.px-3{padding-left:.75rem!important;padding-right:.75rem!important}.py-3{padding-top:.75rem!important;padding-bottom:.75rem!important}.p-4{padding:1rem!important}.pt-4{padding-top:1rem!important}.pr-4{padding-right:1rem!important}.pb-4{padding-bottom:1rem!important}.pl-4{padding-left:1rem!important}.px-4{padding-left:1rem!important;padding-right:1rem!important}.py-4{padding-top:1rem!important;padding-bottom:1rem!important}.p-5{padding:1.5rem!important}.pt-5{padding-top:1.5rem!important}.pr-5{padding-right:1.5rem!important}.pb-5{padding-bottom:1.5rem!important}.pl-5{padding-left:1.5rem!important}.px-5{padding-left:1.5rem!important;padding-right:1.5rem!important}.py-5{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.p-6{padding:3rem!important}.pt-6{padding-top:3rem!important}.pr-6{padding-right:3rem!important}.pb-6{padding-bottom:3rem!important}.pl-6{padding-left:3rem!important}.px-6{padding-left:3rem!important;padding-right:3rem!important}.py-6{padding-top:3rem!important;padding-bottom:3rem!important}.p-auto{padding:auto!important}.pt-auto{padding-top:auto!important}.pr-auto{padding-right:auto!important}.pb-auto{padding-bottom:auto!important}.pl-auto{padding-left:auto!important}.px-auto{padding-left:auto!important;padding-right:auto!important}.py-auto{padding-top:auto!important;padding-bottom:auto!important}.is-size-1{font-size:3rem!important}.is-size-2{font-size:2.5rem!important}.is-size-3{font-size:2rem!important}.is-size-4{font-size:1.5rem!important}.is-size-5{font-size:1.25rem!important}.is-size-6{font-size:1rem!important}.is-size-7{font-size:.75rem!important}@media screen and (max-width:768px){.is-size-1-mobile{font-size:3rem!important}.is-size-2-mobile{font-size:2.5rem!important}.is-size-3-mobile{font-size:2rem!important}.is-size-4-mobile{font-size:1.5rem!important}.is-size-5-mobile{font-size:1.25rem!important}.is-size-6-mobile{font-size:1rem!important}.is-size-7-mobile{font-size:.75rem!important}}@media screen and (min-width:769px),print{.is-size-1-tablet{font-size:3rem!important}.is-size-2-tablet{font-size:2.5rem!important}.is-size-3-tablet{font-size:2rem!important}.is-size-4-tablet{font-size:1.5rem!important}.is-size-5-tablet{font-size:1.25rem!important}.is-size-6-tablet{font-size:1rem!important}.is-size-7-tablet{font-size:.75rem!important}}@media screen and (max-width:1023px){.is-size-1-touch{font-size:3rem!important}.is-size-2-touch{font-size:2.5rem!important}.is-size-3-touch{font-size:2rem!important}.is-size-4-touch{font-size:1.5rem!important}.is-size-5-touch{font-size:1.25rem!important}.is-size-6-touch{font-size:1rem!important}.is-size-7-touch{font-size:.75rem!important}}@media screen and (min-width:1024px){.is-size-1-desktop{font-size:3rem!important}.is-size-2-desktop{font-size:2.5rem!important}.is-size-3-desktop{font-size:2rem!important}.is-size-4-desktop{font-size:1.5rem!important}.is-size-5-desktop{font-size:1.25rem!important}.is-size-6-desktop{font-size:1rem!important}.is-size-7-desktop{font-size:.75rem!important}}@media screen and (min-width:1216px){.is-size-1-widescreen{font-size:3rem!important}.is-size-2-widescreen{font-size:2.5rem!important}.is-size-3-widescreen{font-size:2rem!important}.is-size-4-widescreen{font-size:1.5rem!important}.is-size-5-widescreen{font-size:1.25rem!important}.is-size-6-widescreen{font-size:1rem!important}.is-size-7-widescreen{font-size:.75rem!important}}@media screen and (min-width:1408px){.is-size-1-fullhd{font-size:3rem!important}.is-size-2-fullhd{font-size:2.5rem!important}.is-size-3-fullhd{font-size:2rem!important}.is-size-4-fullhd{font-size:1.5rem!important}.is-size-5-fullhd{font-size:1.25rem!important}.is-size-6-fullhd{font-size:1rem!important}.is-size-7-fullhd{font-size:.75rem!important}}.has-text-centered{text-align:center!important}.has-text-justified{text-align:justify!important}.has-text-left{text-align:left!important}.has-text-right{text-align:right!important}@media screen and (max-width:768px){.has-text-centered-mobile{text-align:center!important}}@media screen and (min-width:769px),print{.has-text-centered-tablet{text-align:center!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-centered-tablet-only{text-align:center!important}}@media screen and (max-width:1023px){.has-text-centered-touch{text-align:center!important}}@media screen and (min-width:1024px){.has-text-centered-desktop{text-align:center!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-centered-desktop-only{text-align:center!important}}@media screen and (min-width:1216px){.has-text-centered-widescreen{text-align:center!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-centered-widescreen-only{text-align:center!important}}@media screen and (min-width:1408px){.has-text-centered-fullhd{text-align:center!important}}@media screen and (max-width:768px){.has-text-justified-mobile{text-align:justify!important}}@media screen and (min-width:769px),print{.has-text-justified-tablet{text-align:justify!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-justified-tablet-only{text-align:justify!important}}@media screen and (max-width:1023px){.has-text-justified-touch{text-align:justify!important}}@media screen and (min-width:1024px){.has-text-justified-desktop{text-align:justify!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-justified-desktop-only{text-align:justify!important}}@media screen and (min-width:1216px){.has-text-justified-widescreen{text-align:justify!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-justified-widescreen-only{text-align:justify!important}}@media screen and (min-width:1408px){.has-text-justified-fullhd{text-align:justify!important}}@media screen and (max-width:768px){.has-text-left-mobile{text-align:left!important}}@media screen and (min-width:769px),print{.has-text-left-tablet{text-align:left!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-left-tablet-only{text-align:left!important}}@media screen and (max-width:1023px){.has-text-left-touch{text-align:left!important}}@media screen and (min-width:1024px){.has-text-left-desktop{text-align:left!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-left-desktop-only{text-align:left!important}}@media screen and (min-width:1216px){.has-text-left-widescreen{text-align:left!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-left-widescreen-only{text-align:left!important}}@media screen and (min-width:1408px){.has-text-left-fullhd{text-align:left!important}}@media screen and (max-width:768px){.has-text-right-mobile{text-align:right!important}}@media screen and (min-width:769px),print{.has-text-right-tablet{text-align:right!important}}@media screen and (min-width:769px) and (max-width:1023px){.has-text-right-tablet-only{text-align:right!important}}@media screen and (max-width:1023px){.has-text-right-touch{text-align:right!important}}@media screen and (min-width:1024px){.has-text-right-desktop{text-align:right!important}}@media screen and (min-width:1024px) and (max-width:1215px){.has-text-right-desktop-only{text-align:right!important}}@media screen and (min-width:1216px){.has-text-right-widescreen{text-align:right!important}}@media screen and (min-width:1216px) and (max-width:1407px){.has-text-right-widescreen-only{text-align:right!important}}@media screen and (min-width:1408px){.has-text-right-fullhd{text-align:right!important}}.is-capitalized{text-transform:capitalize!important}.is-lowercase{text-transform:lowercase!important}.is-uppercase{text-transform:uppercase!important}.is-italic{font-style:italic!important}.is-underlined{text-decoration:underline!important}.has-text-weight-light{font-weight:300!important}.has-text-weight-normal{font-weight:400!important}.has-text-weight-medium{font-weight:500!important}.has-text-weight-semibold{font-weight:600!important}.has-text-weight-bold{font-weight:700!important}.is-family-primary{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-secondary{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-sans-serif{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif!important}.is-family-monospace{font-family:monospace!important}.is-family-code{font-family:monospace!important}.is-block{display:block!important}@media screen and (max-width:768px){.is-block-mobile{display:block!important}}@media screen and (min-width:769px),print{.is-block-tablet{display:block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-block-tablet-only{display:block!important}}@media screen and (max-width:1023px){.is-block-touch{display:block!important}}@media screen and (min-width:1024px){.is-block-desktop{display:block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-block-desktop-only{display:block!important}}@media screen and (min-width:1216px){.is-block-widescreen{display:block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-block-widescreen-only{display:block!important}}@media screen and (min-width:1408px){.is-block-fullhd{display:block!important}}.is-flex{display:flex!important}@media screen and (max-width:768px){.is-flex-mobile{display:flex!important}}@media screen and (min-width:769px),print{.is-flex-tablet{display:flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-flex-tablet-only{display:flex!important}}@media screen and (max-width:1023px){.is-flex-touch{display:flex!important}}@media screen and (min-width:1024px){.is-flex-desktop{display:flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-flex-desktop-only{display:flex!important}}@media screen and (min-width:1216px){.is-flex-widescreen{display:flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-flex-widescreen-only{display:flex!important}}@media screen and (min-width:1408px){.is-flex-fullhd{display:flex!important}}.is-inline{display:inline!important}@media screen and (max-width:768px){.is-inline-mobile{display:inline!important}}@media screen and (min-width:769px),print{.is-inline-tablet{display:inline!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-tablet-only{display:inline!important}}@media screen and (max-width:1023px){.is-inline-touch{display:inline!important}}@media screen and (min-width:1024px){.is-inline-desktop{display:inline!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-desktop-only{display:inline!important}}@media screen and (min-width:1216px){.is-inline-widescreen{display:inline!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-widescreen-only{display:inline!important}}@media screen and (min-width:1408px){.is-inline-fullhd{display:inline!important}}.is-inline-block{display:inline-block!important}@media screen and (max-width:768px){.is-inline-block-mobile{display:inline-block!important}}@media screen and (min-width:769px),print{.is-inline-block-tablet{display:inline-block!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-block-tablet-only{display:inline-block!important}}@media screen and (max-width:1023px){.is-inline-block-touch{display:inline-block!important}}@media screen and (min-width:1024px){.is-inline-block-desktop{display:inline-block!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-block-desktop-only{display:inline-block!important}}@media screen and (min-width:1216px){.is-inline-block-widescreen{display:inline-block!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-block-widescreen-only{display:inline-block!important}}@media screen and (min-width:1408px){.is-inline-block-fullhd{display:inline-block!important}}.is-inline-flex{display:inline-flex!important}@media screen and (max-width:768px){.is-inline-flex-mobile{display:inline-flex!important}}@media screen and (min-width:769px),print{.is-inline-flex-tablet{display:inline-flex!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-inline-flex-tablet-only{display:inline-flex!important}}@media screen and (max-width:1023px){.is-inline-flex-touch{display:inline-flex!important}}@media screen and (min-width:1024px){.is-inline-flex-desktop{display:inline-flex!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-inline-flex-desktop-only{display:inline-flex!important}}@media screen and (min-width:1216px){.is-inline-flex-widescreen{display:inline-flex!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-inline-flex-widescreen-only{display:inline-flex!important}}@media screen and (min-width:1408px){.is-inline-flex-fullhd{display:inline-flex!important}}.is-hidden{display:none!important}.is-sr-only{border:none!important;clip:rect(0,0,0,0)!important;height:.01em!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:.01em!important}@media screen and (max-width:768px){.is-hidden-mobile{display:none!important}}@media screen and (min-width:769px),print{.is-hidden-tablet{display:none!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-hidden-tablet-only{display:none!important}}@media screen and (max-width:1023px){.is-hidden-touch{display:none!important}}@media screen and (min-width:1024px){.is-hidden-desktop{display:none!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-hidden-desktop-only{display:none!important}}@media screen and (min-width:1216px){.is-hidden-widescreen{display:none!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-hidden-widescreen-only{display:none!important}}@media screen and (min-width:1408px){.is-hidden-fullhd{display:none!important}}.is-invisible{visibility:hidden!important}@media screen and (max-width:768px){.is-invisible-mobile{visibility:hidden!important}}@media screen and (min-width:769px),print{.is-invisible-tablet{visibility:hidden!important}}@media screen and (min-width:769px) and (max-width:1023px){.is-invisible-tablet-only{visibility:hidden!important}}@media screen and (max-width:1023px){.is-invisible-touch{visibility:hidden!important}}@media screen and (min-width:1024px){.is-invisible-desktop{visibility:hidden!important}}@media screen and (min-width:1024px) and (max-width:1215px){.is-invisible-desktop-only{visibility:hidden!important}}@media screen and (min-width:1216px){.is-invisible-widescreen{visibility:hidden!important}}@media screen and (min-width:1216px) and (max-width:1407px){.is-invisible-widescreen-only{visibility:hidden!important}}@media screen and (min-width:1408px){.is-invisible-fullhd{visibility:hidden!important}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:0 0}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width:1023px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,.7)}.hero.is-white .navbar-link.is-active,.hero.is-white .navbar-link:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white a.navbar-item:hover{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff!important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg,#e6e6e6 0,#fff 71%,#fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,.7)}.hero.is-black .navbar-link.is-active,.hero.is-black .navbar-link:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black a.navbar-item:hover{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a!important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}@media screen and (max-width:768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg,#000 0,#0a0a0a 71%,#181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,.7)}.hero.is-light .subtitle{color:rgba(0,0,0,.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,.7)}@media screen and (max-width:1023px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,.7)}.hero.is-light .navbar-link.is-active,.hero.is-light .navbar-link:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light a.navbar-item:hover{background-color:#e8e8e8;color:rgba(0,0,0,.7)}.hero.is-light .tabs a{color:rgba(0,0,0,.7);opacity:.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5!important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,.7);border-color:rgba(0,0,0,.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}@media screen and (max-width:768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg,#dfd8d9 0,#f5f5f5 71%,#fff 100%)}}.hero.is-dark{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong{color:inherit}.hero.is-dark .title{color:#fff}.hero.is-dark .subtitle{color:rgba(255,255,255,.9)}.hero.is-dark .subtitle a:not(.button),.hero.is-dark .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-dark .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.hero.is-dark .navbar-link{color:rgba(255,255,255,.7)}.hero.is-dark .navbar-link.is-active,.hero.is-dark .navbar-link:hover,.hero.is-dark a.navbar-item.is-active,.hero.is-dark a.navbar-item:hover{background-color:#292929;color:#fff}.hero.is-dark .tabs a{color:#fff;opacity:.9}.hero.is-dark .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a{color:#363636!important;opacity:1}.hero.is-dark .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}@media screen and (max-width:768px){.hero.is-dark.is-bold .navbar-menu{background-image:linear-gradient(141deg,#1f191a 0,#363636 71%,#46403f 100%)}}.hero.is-primary{background-color:#00d1b2;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong{color:inherit}.hero.is-primary .title{color:#fff}.hero.is-primary .subtitle{color:rgba(255,255,255,.9)}.hero.is-primary .subtitle a:not(.button),.hero.is-primary .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-primary .navbar-menu{background-color:#00d1b2}}.hero.is-primary .navbar-item,.hero.is-primary .navbar-link{color:rgba(255,255,255,.7)}.hero.is-primary .navbar-link.is-active,.hero.is-primary .navbar-link:hover,.hero.is-primary a.navbar-item.is-active,.hero.is-primary a.navbar-item:hover{background-color:#00b89c;color:#fff}.hero.is-primary .tabs a{color:#fff;opacity:.9}.hero.is-primary .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a{color:#00d1b2!important;opacity:1}.hero.is-primary .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#00d1b2}.hero.is-primary.is-bold{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}@media screen and (max-width:768px){.hero.is-primary.is-bold .navbar-menu{background-image:linear-gradient(141deg,#009e6c 0,#00d1b2 71%,#00e7eb 100%)}}.hero.is-link{background-color:#485fc7;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-link .navbar-menu{background-color:#485fc7}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,.7)}.hero.is-link .navbar-link.is-active,.hero.is-link .navbar-link:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link a.navbar-item:hover{background-color:#3a51bb;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#485fc7!important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#485fc7}.hero.is-link.is-bold{background-image:linear-gradient(141deg,#2959b3 0,#485fc7 71%,#5658d2 100%)}@media screen and (max-width:768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg,#2959b3 0,#485fc7 71%,#5658d2 100%)}}.hero.is-info{background-color:#3e8ed0;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-info .navbar-menu{background-color:#3e8ed0}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,.7)}.hero.is-info .navbar-link.is-active,.hero.is-info .navbar-link:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info a.navbar-item:hover{background-color:#3082c5;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#3e8ed0!important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#3e8ed0}.hero.is-info.is-bold{background-image:linear-gradient(141deg,#208fbc 0,#3e8ed0 71%,#4d83db 100%)}@media screen and (max-width:768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg,#208fbc 0,#3e8ed0 71%,#4d83db 100%)}}.hero.is-success{background-color:#48c78e;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-success .navbar-menu{background-color:#48c78e}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,.7)}.hero.is-success .navbar-link.is-active,.hero.is-success .navbar-link:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success a.navbar-item:hover{background-color:#3abb81;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#48c78e!important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#48c78e}.hero.is-success.is-bold{background-image:linear-gradient(141deg,#29b35e 0,#48c78e 71%,#56d2af 100%)}@media screen and (max-width:768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg,#29b35e 0,#48c78e 71%,#56d2af 100%)}}.hero.is-warning{background-color:#ffe08a;color:rgba(0,0,0,.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,.7)}@media screen and (max-width:1023px){.hero.is-warning .navbar-menu{background-color:#ffe08a}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,.7)}.hero.is-warning .navbar-link.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning a.navbar-item:hover{background-color:#ffd970;color:rgba(0,0,0,.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,.7);opacity:.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffe08a!important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,.7);border-color:rgba(0,0,0,.7);color:#ffe08a}.hero.is-warning.is-bold{background-image:linear-gradient(141deg,#ffb657 0,#ffe08a 71%,#fff6a3 100%)}@media screen and (max-width:768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg,#ffb657 0,#ffe08a 71%,#fff6a3 100%)}}.hero.is-danger{background-color:#f14668;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width:1023px){.hero.is-danger .navbar-menu{background-color:#f14668}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,.7)}.hero.is-danger .navbar-link.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger a.navbar-item:hover{background-color:#ef2e55;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#f14668!important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#f14668}.hero.is-danger.is-bold{background-image:linear-gradient(141deg,#fa0a62 0,#f14668 71%,#f7595f 100%)}@media screen and (max-width:768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg,#fa0a62 0,#f14668 71%,#f7595f 100%)}}.hero.is-small .hero-body{padding:1.5rem}@media screen and (min-width:769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width:769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body,.hero.is-halfheight .hero-body{align-items:center;display:flex}.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container,.hero.is-halfheight .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.hero-video.is-transparent{opacity:.3}@media screen and (max-width:768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width:768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:.75rem}}@media screen and (min-width:769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-foot,.hero-head{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width:769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width:1024px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem} \ No newline at end of file diff --git a/pagetop/static/bulmix/css/bulma.min.css.map b/pagetop/static/bulmix/css/bulma.min.css.map new file mode 100644 index 00000000..fc794a72 --- /dev/null +++ b/pagetop/static/bulmix/css/bulma.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../bulma.sass","../sass/utilities/_all.sass","../sass/utilities/extends.sass","../sass/utilities/controls.sass","../sass/utilities/initial-variables.sass","bulma.css","../sass/utilities/mixins.sass","../sass/base/_all.sass","../sass/base/minireset.sass","../sass/base/generic.sass","../sass/utilities/derived-variables.sass","../sass/base/animations.sass","../sass/elements/_all.sass","../sass/elements/box.sass","../sass/elements/button.sass","../sass/utilities/functions.sass","../sass/elements/container.sass","../sass/elements/content.sass","../sass/elements/icon.sass","../sass/elements/image.sass","../sass/elements/notification.sass","../sass/elements/progress.sass","../sass/elements/table.sass","../sass/elements/tag.sass","../sass/elements/title.sass","../sass/elements/other.sass","../sass/form/_all.sass","../sass/form/shared.sass","../sass/form/input-textarea.sass","../sass/form/checkbox-radio.sass","../sass/form/select.sass","../sass/form/file.sass","../sass/form/tools.sass","../sass/components/_all.sass","../sass/components/breadcrumb.sass","../sass/components/card.sass","../sass/components/dropdown.sass","../sass/components/level.sass","../sass/components/media.sass","../sass/components/menu.sass","../sass/components/message.sass","../sass/components/modal.sass","../sass/components/navbar.sass","../sass/components/pagination.sass","../sass/components/panel.sass","../sass/components/tabs.sass","../sass/grid/_all.sass","../sass/grid/columns.sass","../sass/grid/tiles.sass","../sass/helpers/_all.sass","../sass/helpers/color.sass","../sass/helpers/flexbox.sass","../sass/helpers/float.sass","../sass/helpers/other.sass","../sass/helpers/overflow.sass","../sass/helpers/position.sass","../sass/helpers/spacing.sass","../sass/helpers/typography.sass","../sass/helpers/visibility.sass","../sass/layout/_all.sass","../sass/layout/hero.sass","../sass/layout/section.sass","../sass/layout/footer.sass"],"names":[],"mappings":"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,4BAA4B;EAC5B,sBLpC0B;ACkU5B;;AI5RA;EACE,cL7D4B;EK8D5B,cA1DkB;EA2DlB,gBL7BiB;EK8BjB,gBA1DoB;AJyVtB;;AI3RA;EACE,cLtDgC;EKuDhC,eAAe;EACf,qBAAqB;AJ8RvB;;AIjSA;EAKI,mBAAmB;AJgSvB;;AIrSA;EAOI,cL5E0B;AC8W9B;;AIhSA;EACE,4BLxE4B;EKyE5B,cCnBsB;EDoBtB,kBArEiB;EAsEjB,mBAvEkB;EAwElB,4BAzEgC;AJ4WlC;;AIjSA;EACE,4BL/E4B;EKgF5B,YAAY;EACZ,cAAc;EACd,WAxEa;EAyEb,gBAxEkB;AJ4WpB;;AIlSA;EACE,YAAY;EACZ,eAAe;AJqSjB;;AInSA;;EAEE,wBAAwB;AJsS1B;;AIpSA;EACE,kBAvFuB;AJ8XzB;;AIrSA;EACE,mBAAmB;EACnB,oBAAoB;AJwStB;;AItSA;EACE,cL5G4B;EK6G5B,gBLvEe;ACgXjB;;AIrSA;EACE,YAAY;AJwSd;;AItSA;EH5DE,iCAAiC;EG8DjC,4BL/G4B;EKgH5B,cLtH4B;EKuH5B,kBAjGqB;EAkGrB,gBAAgB;EAChB,uBAlG0B;EAmG1B,gBAAgB;EAChB,iBAAiB;AJySnB;;AIjTA;EAUI,6BAA6B;EAC7B,mBAAmB;EACnB,cAvGoB;EAwGpB,UAAU;AJ2Sd;;AIzSA;;EAGI,mBAAmB;AJ2SvB;;AI9SA;;EAKM,mBAAmB;AJ8SzB;;AInTA;EAOI,cL1I0B;AC0b9B;;AMhcA;EACE;IACE,uBAAuB;ENmczB;EMlcA;IACE,yBAAyB;ENoc3B;AACF;;AMzcA;EACE;IACE,uBAAuB;ENmczB;EMlcA;IACE,yBAAyB;ENoc3B;AACF;;AOzcA,mBAAA;ACWA;EAEE,uBTE6B;ESD7B,kBTwDgB;ESvDhB,0FTb2B;ESc3B,cTT4B;ESU5B,cAAc;EACd,gBAZmB;AR6crB;;AQ/bA;EAGI,yETD8B;ACiclC;;AQncA;EAKI,oETH8B;ACqclC;;AShaA;EAGE,uBV/C6B;EUgD7B,qBVrD4B;EUsD5B,iBX3DwB;EW4DxB,cV3D4B;EU4D5B,eAAe;EAGf,uBAAuB;EACvB,iCA5D6D;EA6D7D,iBA5D6B;EA6D7B,kBA7D6B;EA8D7B,8BA/D6D;EAgE7D,kBAAkB;EAClB,mBAAmB;AT+ZrB;;AS/aA;EAkBI,cAAc;ATialB;;ASnbA;EAwBM,aAAa;EACb,YAAY;AT+ZlB;;ASxbA;ERiGI,+BQtEsG;ERsEtG,oBQrEmE;ATiavE;;AS7bA;ERiGI,mBQnEmE;ERmEnE,gCQlEsG;ATma1G;;ASlcA;EAiCM,+BAAiF;EACjF,gCAAkF;ATqaxF;;ASvcA;EAsCI,qBVxF0B;EUyF1B,cV5F0B;ACigB9B;;AS5cA;EA0CI,qBV/E8B;EUgF9B,cVhG0B;ACsgB9B;;ASjdA;EA6CM,iDVlF4B;AC0flC;;ASrdA;EAgDI,qBVpG0B;EUqG1B,cVtG0B;AC+gB9B;;AS1dA;EAoDI,6BAA6B;EAC7B,yBAAyB;EACzB,cV1G0B;EU2G1B,0BAzF8B;ATmgBlC;;ASjeA;EA4DM,4BV1GwB;EU2GxB,cVlHwB;AC2hB9B;;ASteA;EAgEM,yBCd2B;EDe3B,cVtHwB;ACgiB9B;;AS3eA;;EAoEM,6BAA6B;EAC7B,yBAAyB;EACzB,gBAAgB;AT4atB;;ASlfA;EAwEI,gBAtG0B;EAuG1B,yBAtGmC;EAuGnC,cV/G8B;EUgH9B,qBAtG0B;ATohB9B;;ASzfA;EA8EM,cVnH4B;EUoH5B,0BAxGmC;ATuhBzC;;AS9fA;EAoFM,uBVhIyB;EUiIzB,yBAAyB;EACzB,cV/IuB;AC6jB7B;;ASpgBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,cVpJqB;ACmkB7B;;AS1gBA;EA8FQ,yBAAyB;EACzB,cVxJqB;ACwkB7B;;AS/gBA;EAiGU,mDV7IqB;AC+jB/B;;ASnhBA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,cV/JqB;ACklB7B;;ASzhBA;;EAyGQ,uBVrJuB;EUsJvB,yBAAyB;EACzB,gBAAgB;ATqbxB;;AShiBA;EA6GQ,yBVtKqB;EUuKrB,YV1JuB;ACilB/B;;ASriBA;EAiHU,uBC/DuB;AVufjC;;ASziBA;;EAoHU,yBV7KmB;EU8KnB,yBAAyB;EACzB,gBAAgB;EAChB,YVnKqB;AC6lB/B;;ASjjBA;EA0HU,gEAA4E;AT2btF;;ASrjBA;EA4HQ,6BAA6B;EAC7B,mBVzKuB;EU0KvB,YV1KuB;ACumB/B;;AS3jBA;EAmIU,uBV/KqB;EUgLrB,mBVhLqB;EUiLrB,cV9LmB;AC0nB7B;;ASjkBA;EAwIY,4DAA8D;AT6b1E;;ASrkBA;EA8Ic,gEAA4E;AT2b1F;;ASzkBA;;EAiJU,6BAA6B;EAC7B,mBV9LqB;EU+LrB,gBAAgB;EAChB,YVhMqB;AC6nB/B;;ASjlBA;EAsJQ,6BAA6B;EAC7B,qBVhNqB;EUiNrB,cVjNqB;ACgpB7B;;ASvlBA;EA6JU,yBVtNmB;EUuNnB,YV1MqB;ACwoB/B;;AS5lBA;EAqKc,4DAA8D;AT2b5E;;AShmBA;;EAwKU,6BAA6B;EAC7B,qBVlOmB;EUmOnB,gBAAgB;EAChB,cVpOmB;ACiqB7B;;ASxmBA;EAoFM,yBV7IuB;EU8IvB,yBAAyB;EACzB,YVlIyB;AC0pB/B;;AS9mBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,YVvIuB;ACgqB/B;;ASpnBA;EA8FQ,yBAAyB;EACzB,YV3IuB;ACqqB/B;;ASznBA;EAiGU,gDV1JmB;ACsrB7B;;AS7nBA;EAoGQ,uBClDyB;EDmDzB,yBAAyB;EACzB,YVlJuB;AC+qB/B;;ASnoBA;;EAyGQ,yBVlKqB;EUmKrB,yBAAyB;EACzB,gBAAgB;AT+hBxB;;AS1oBA;EA6GQ,uBVzJuB;EU0JvB,cVvKqB;ACwsB7B;;AS/oBA;EAiHU,yBC/DuB;AVimBjC;;ASnpBA;;EAoHU,uBVhKqB;EUiKrB,yBAAyB;EACzB,gBAAgB;EAChB,cVhLmB;ACotB7B;;AS3pBA;EA0HU,4DAA4E;ATqiBtF;;AS/pBA;EA4HQ,6BAA6B;EAC7B,qBVtLqB;EUuLrB,cVvLqB;AC8tB7B;;ASrqBA;EAmIU,yBV5LmB;EU6LnB,qBV7LmB;EU8LnB,YVjLqB;ACutB/B;;AS3qBA;EAwIY,gEAA8D;ATuiB1E;;AS/qBA;EA8Ic,4DAA4E;ATqiB1F;;ASnrBA;;EAiJU,6BAA6B;EAC7B,qBV3MmB;EU4MnB,gBAAgB;EAChB,cV7MmB;ACovB7B;;AS3rBA;EAsJQ,6BAA6B;EAC7B,mBVnMuB;EUoMvB,YVpMuB;AC6uB/B;;ASjsBA;EA6JU,uBVzMqB;EU0MrB,cVvNmB;AC+vB7B;;AStsBA;EAqKc,gEAA8D;ATqiB5E;;AS1sBA;;EAwKU,6BAA6B;EAC7B,mBVrNqB;EUsNrB,gBAAgB;EAChB,YVvNqB;AC8vB/B;;ASltBA;EAoFM,4BVlIwB;EUmIxB,yBAAyB;EACzB,yBCjEe;AVmsBrB;;ASxtBA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,yBCtEa;AVysBrB;;AS9tBA;EA8FQ,yBAAyB;EACzB,yBC1Ea;AV8sBrB;;ASnuBA;EAiGU,mDV/IoB;ACqxB9B;;ASvuBA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,yBCjFa;AVwtBrB;;AS7uBA;;EAyGQ,4BVvJsB;EUwJtB,yBAAyB;EACzB,gBAAgB;ATyoBxB;;ASpvBA;EA6GQ,oCCxFa;EDyFb,iBV5JsB;ACuyB9B;;ASzvBA;EAiHU,oCC/DuB;AV2sBjC;;AS7vBA;;EAoHU,oCC/FW;EDgGX,yBAAyB;EACzB,gBAAgB;EAChB,iBVrKoB;ACmzB9B;;ASrwBA;EA0HU,sFAA4E;AT+oBtF;;ASzwBA;EA4HQ,6BAA6B;EAC7B,wBV3KsB;EU4KtB,iBV5KsB;AC6zB9B;;AS/wBA;EAmIU,4BVjLoB;EUkLpB,wBVlLoB;EUmLpB,yBChHW;AVgwBrB;;ASrxBA;EAwIY,sEAA8D;ATipB1E;;ASzxBA;EA8Ic,sFAA4E;AT+oB1F;;AS7xBA;;EAiJU,6BAA6B;EAC7B,wBVhMoB;EUiMpB,gBAAgB;EAChB,iBVlMoB;ACm1B9B;;ASryBA;EAsJQ,6BAA6B;EAC7B,gCClIa;EDmIb,yBCnIa;AVsxBrB;;AS3yBA;EA6JU,oCCxIW;EDyIX,iBV5MoB;AC81B9B;;AShzBA;EAqKc,sEAA8D;AT+oB5E;;ASpzBA;;EAwKU,6BAA6B;EAC7B,gCCpJW;EDqJX,gBAAgB;EAChB,yBCtJW;AVuyBrB;;AS5zBA;EAoFM,yBVzIwB;EU0IxB,yBAAyB;EACzB,WC/DU;AV2yBhB;;ASl0BA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVizBhB;;ASx0BA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVszBhB;;AS70BA;EAiGU,gDVtJoB;ACs4B9B;;ASj1BA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVg0BhB;;ASv1BA;;EAyGQ,yBV9JsB;EU+JtB,yBAAyB;EACzB,gBAAgB;ATmvBxB;;AS91BA;EA6GQ,sBCtFQ;EDuFR,cVnKsB;ACw5B9B;;ASn2BA;EAiHU,yBC/DuB;AVqzBjC;;ASv2BA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV5KoB;ACo6B9B;;AS/2BA;EA0HU,0DAA4E;ATyvBtF;;ASn3BA;EA4HQ,6BAA6B;EAC7B,qBVlLsB;EUmLtB,cVnLsB;AC86B9B;;ASz3BA;EAmIU,yBVxLoB;EUyLpB,qBVzLoB;EU0LpB,WC9GM;AVw2BhB;;AS/3BA;EAwIY,gEAA8D;AT2vB1E;;ASn4BA;EA8Ic,0DAA4E;ATyvB1F;;ASv4BA;;EAiJU,6BAA6B;EAC7B,qBVvMoB;EUwMpB,gBAAgB;EAChB,cVzMoB;ACo8B9B;;AS/4BA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV83BhB;;ASr5BA;EA6JU,sBCtIM;EDuIN,cVnNoB;AC+8B9B;;AS15BA;EAqKc,gEAA8D;ATyvB5E;;AS95BA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV+4BhB;;ASt6BA;EAoFM,yBV3H4B;EU4H5B,yBAAyB;EACzB,WC/DU;AVq5BhB;;AS56BA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AV25BhB;;ASl7BA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVg6BhB;;ASv7BA;EAiGU,iDVxIwB;ACk+BlC;;AS37BA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AV06BhB;;ASj8BA;;EAyGQ,yBVhJ0B;EUiJ1B,yBAAyB;EACzB,gBAAgB;AT61BxB;;ASx8BA;EA6GQ,sBCtFQ;EDuFR,cVrJ0B;ACo/BlC;;AS78BA;EAiHU,yBC/DuB;AV+5BjC;;ASj9BA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV9JwB;ACggClC;;ASz9BA;EA0HU,0DAA4E;ATm2BtF;;AS79BA;EA4HQ,6BAA6B;EAC7B,qBVpK0B;EUqK1B,cVrK0B;AC0gClC;;ASn+BA;EAmIU,yBV1KwB;EU2KxB,qBV3KwB;EU4KxB,WC9GM;AVk9BhB;;ASz+BA;EAwIY,gEAA8D;ATq2B1E;;AS7+BA;EA8Ic,0DAA4E;ATm2B1F;;ASj/BA;;EAiJU,6BAA6B;EAC7B,qBVzLwB;EU0LxB,gBAAgB;EAChB,cV3LwB;ACgiClC;;ASz/BA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVw+BhB;;AS//BA;EA6JU,sBCtIM;EDuIN,cVrMwB;AC2iClC;;ASpgCA;EAqKc,gEAA8D;ATm2B5E;;ASxgCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVy/BhB;;AShhCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV8+BrE;;ASrhCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVo/BrE;;AS3hCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AV0/BrE;;ASjiCA;EAoFM,yBVzH4B;EU0H5B,yBAAyB;EACzB,WC/DU;AVghChB;;ASviCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVshChB;;AS7iCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AV2hChB;;ASljCA;EAiGU,iDVtIwB;AC2lClC;;AStjCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVqiChB;;AS5jCA;;EAyGQ,yBV9I0B;EU+I1B,yBAAyB;EACzB,gBAAgB;ATw9BxB;;ASnkCA;EA6GQ,sBCtFQ;EDuFR,cVnJ0B;AC6mClC;;ASxkCA;EAiHU,yBC/DuB;AV0hCjC;;AS5kCA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV5JwB;ACynClC;;ASplCA;EA0HU,0DAA4E;AT89BtF;;ASxlCA;EA4HQ,6BAA6B;EAC7B,qBVlK0B;EUmK1B,cVnK0B;ACmoClC;;AS9lCA;EAmIU,yBVxKwB;EUyKxB,qBVzKwB;EU0KxB,WC9GM;AV6kChB;;ASpmCA;EAwIY,gEAA8D;ATg+B1E;;ASxmCA;EA8Ic,0DAA4E;AT89B1F;;AS5mCA;;EAiJU,6BAA6B;EAC7B,qBVvLwB;EUwLxB,gBAAgB;EAChB,cVzLwB;ACypClC;;ASpnCA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVmmChB;;AS1nCA;EA6JU,sBCtIM;EDuIN,cVnMwB;ACoqClC;;AS/nCA;EAqKc,gEAA8D;AT89B5E;;ASnoCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVonChB;;AS3oCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVymCrE;;AShpCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV+mCrE;;AStpCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVqnCrE;;AS5pCA;EAoFM,yBV1H4B;EU2H5B,yBAAyB;EACzB,WC/DU;AV2oChB;;ASlqCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVipChB;;ASxqCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVspChB;;AS7qCA;EAiGU,kDVvIwB;ACutClC;;ASjrCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVgqChB;;ASvrCA;;EAyGQ,yBV/I0B;EUgJ1B,yBAAyB;EACzB,gBAAgB;ATmlCxB;;AS9rCA;EA6GQ,sBCtFQ;EDuFR,cVpJ0B;ACyuClC;;ASnsCA;EAiHU,yBC/DuB;AVqpCjC;;ASvsCA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV7JwB;ACqvClC;;AS/sCA;EA0HU,0DAA4E;ATylCtF;;ASntCA;EA4HQ,6BAA6B;EAC7B,qBVnK0B;EUoK1B,cVpK0B;AC+vClC;;ASztCA;EAmIU,yBVzKwB;EU0KxB,qBV1KwB;EU2KxB,WC9GM;AVwsChB;;AS/tCA;EAwIY,gEAA8D;AT2lC1E;;ASnuCA;EA8Ic,0DAA4E;ATylC1F;;ASvuCA;;EAiJU,6BAA6B;EAC7B,qBVxLwB;EUyLxB,gBAAgB;EAChB,cV1LwB;ACqxClC;;AS/uCA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV8tChB;;ASrvCA;EA6JU,sBCtIM;EDuIN,cVpMwB;ACgyClC;;AS1vCA;EAqKc,gEAA8D;ATylC5E;;AS9vCA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV+uChB;;AStwCA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVouCrE;;AS3wCA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV0uCrE;;ASjxCA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVgvCrE;;ASvxCA;EAoFM,yBV5H4B;EU6H5B,yBAAyB;EACzB,WC/DU;AVswChB;;AS7xCA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AV4wChB;;ASnyCA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVixChB;;ASxyCA;EAiGU,kDVzIwB;ACo1ClC;;AS5yCA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AV2xChB;;ASlzCA;;EAyGQ,yBVjJ0B;EUkJ1B,yBAAyB;EACzB,gBAAgB;AT8sCxB;;ASzzCA;EA6GQ,sBCtFQ;EDuFR,cVtJ0B;ACs2ClC;;AS9zCA;EAiHU,yBC/DuB;AVgxCjC;;ASl0CA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV/JwB;ACk3ClC;;AS10CA;EA0HU,0DAA4E;ATotCtF;;AS90CA;EA4HQ,6BAA6B;EAC7B,qBVrK0B;EUsK1B,cVtK0B;AC43ClC;;ASp1CA;EAmIU,yBV3KwB;EU4KxB,qBV5KwB;EU6KxB,WC9GM;AVm0ChB;;AS11CA;EAwIY,gEAA8D;ATstC1E;;AS91CA;EA8Ic,0DAA4E;ATotC1F;;ASl2CA;;EAiJU,6BAA6B;EAC7B,qBV1LwB;EU2LxB,gBAAgB;EAChB,cV5LwB;ACk5ClC;;AS12CA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AVy1ChB;;ASh3CA;EA6JU,sBCtIM;EDuIN,cVtMwB;AC65ClC;;ASr3CA;EAqKc,gEAA8D;ATotC5E;;ASz3CA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AV02ChB;;ASj4CA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV+1CrE;;ASt4CA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVq2CrE;;AS54CA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AV22CrE;;ASl5CA;EAoFM,yBV7H4B;EU8H5B,yBAAyB;EACzB,yBCjEe;AVm4CrB;;ASx5CA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,yBCtEa;AVy4CrB;;AS95CA;EA8FQ,yBAAyB;EACzB,yBC1Ea;AV84CrB;;ASn6CA;EAiGU,mDV1IwB;ACg9ClC;;ASv6CA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,yBCjFa;AVw5CrB;;AS76CA;;EAyGQ,yBVlJ0B;EUmJ1B,yBAAyB;EACzB,gBAAgB;ATy0CxB;;ASp7CA;EA6GQ,oCCxFa;EDyFb,cVvJ0B;ACk+ClC;;ASz7CA;EAiHU,oCC/DuB;AV24CjC;;AS77CA;;EAoHU,oCC/FW;EDgGX,yBAAyB;EACzB,gBAAgB;EAChB,cVhKwB;AC8+ClC;;ASr8CA;EA0HU,sFAA4E;AT+0CtF;;ASz8CA;EA4HQ,6BAA6B;EAC7B,qBVtK0B;EUuK1B,cVvK0B;ACw/ClC;;AS/8CA;EAmIU,yBV5KwB;EU6KxB,qBV7KwB;EU8KxB,yBChHW;AVg8CrB;;ASr9CA;EAwIY,gEAA8D;ATi1C1E;;ASz9CA;EA8Ic,sFAA4E;AT+0C1F;;AS79CA;;EAiJU,6BAA6B;EAC7B,qBV3LwB;EU4LxB,gBAAgB;EAChB,cV7LwB;AC8gDlC;;ASr+CA;EAsJQ,6BAA6B;EAC7B,gCClIa;EDmIb,yBCnIa;AVs9CrB;;AS3+CA;EA6JU,oCCxIW;EDyIX,cVvMwB;ACyhDlC;;ASh/CA;EAqKc,gEAA8D;AT+0C5E;;ASp/CA;;EAwKU,6BAA6B;EAC7B,gCCpJW;EDqJX,gBAAgB;EAChB,yBCtJW;AVu+CrB;;AS5/CA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AV09CrE;;ASjgDA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AVg+CrE;;ASvgDA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVs+CrE;;AS7gDA;EAoFM,yBVvH2B;EUwH3B,yBAAyB;EACzB,WC/DU;AV4/ChB;;ASnhDA;EAyFQ,yBCvCyB;EDwCzB,yBAAyB;EACzB,WCpEQ;AVkgDhB;;ASzhDA;EA8FQ,yBAAyB;EACzB,WCxEQ;AVugDhB;;AS9hDA;EAiGU,kDVpIuB;ACqkDjC;;ASliDA;EAoGQ,yBClDyB;EDmDzB,yBAAyB;EACzB,WC/EQ;AVihDhB;;ASxiDA;;EAyGQ,yBV5IyB;EU6IzB,yBAAyB;EACzB,gBAAgB;ATo8CxB;;AS/iDA;EA6GQ,sBCtFQ;EDuFR,cVjJyB;ACulDjC;;ASpjDA;EAiHU,yBC/DuB;AVsgDjC;;ASxjDA;;EAoHU,sBC7FM;ED8FN,yBAAyB;EACzB,gBAAgB;EAChB,cV1JuB;ACmmDjC;;AShkDA;EA0HU,0DAA4E;AT08CtF;;ASpkDA;EA4HQ,6BAA6B;EAC7B,qBVhKyB;EUiKzB,cVjKyB;AC6mDjC;;AS1kDA;EAmIU,yBVtKuB;EUuKvB,qBVvKuB;EUwKvB,WC9GM;AVyjDhB;;AShlDA;EAwIY,gEAA8D;AT48C1E;;ASplDA;EA8Ic,0DAA4E;AT08C1F;;ASxlDA;;EAiJU,6BAA6B;EAC7B,qBVrLuB;EUsLvB,gBAAgB;EAChB,cVvLuB;ACmoDjC;;AShmDA;EAsJQ,6BAA6B;EAC7B,kBChIQ;EDiIR,WCjIQ;AV+kDhB;;AStmDA;EA6JU,sBCtIM;EDuIN,cVjMuB;AC8oDjC;;AS3mDA;EAqKc,gEAA8D;AT08C5E;;AS/mDA;;EAwKU,6BAA6B;EAC7B,kBClJM;EDmJN,gBAAgB;EAChB,WCpJM;AVgmDhB;;ASvnDA;EAiLU,yBCnJsC;EDoJtC,cC3I2D;AVqlDrE;;AS5nDA;EAqLY,yBCnIqB;EDoIrB,yBAAyB;EACzB,cChJyD;AV2lDrE;;ASloDA;EA0LY,yBCxIqB;EDyIrB,yBAAyB;EACzB,cCrJyD;AVimDrE;;ASxoDA;EARE,kBVbc;ACiqDhB;;AStpDE;EACE,kBVkBc;ACuoDlB;;AShpDA;EANE,eVhBW;AC0qDb;;ASppDA;EAJE,kBVnBc;AC+qDhB;;ASxpDA;EAFE,iBVtBa;ACorDf;;AS5pDA;;EAyMI,uBVrP2B;EUsP3B,qBV3P0B;EU4P1B,gBAhOyB;EAiOzB,YAhOyB;ATwrD7B;;ASpqDA;EA8MI,aAAa;EACb,WAAW;AT09Cf;;ASzqDA;EAiNI,6BAA6B;EAC7B,oBAAoB;AT49CxB;;AS9qDA;ERlDE,kBAAkB;EAKhB,6BAAmC;EACnC,4BAAkC;EQkQhC,6BAA6B;AT+9CnC;;ASrrDA;EAwNI,4BVtQ0B;EUuQ1B,qBV1Q0B;EU2Q1B,cV7Q0B;EU8Q1B,gBAAgB;EAChB,oBAAoB;ATi+CxB;;AS7rDA;EA8NI,qBVlNmB;EUmNnB,gCAA0D;EAC1D,iCAA2D;ATm+C/D;;ASj+CA;EACE,mBAAmB;EACnB,aAAa;EACb,eAAe;EACf,2BAA2B;ATo+C7B;;ASx+CA;EAMI,qBAAqB;ATs+CzB;;AS5+CA;ERjII,oBQyIwC;ATw+C5C;;ASh/CA;EAUI,sBAAsB;AT0+C1B;;ASp/CA;EAYI,mBAAmB;AT4+CvB;;ASx/CA;EA1OE,kBVbc;ACmvDhB;;ASxuDE;EACE,kBVkBc;ACytDlB;;AShgDA;EAtOE,kBVnBc;AC6vDhB;;ASpgDA;EApOE,iBVtBa;ACkwDf;;ASxgDA;EA0BQ,4BAA4B;EAC5B,yBAAyB;ATk/CjC;;AS7gDA;EA6BQ,6BAA6B;EAC7B,0BAA0B;ER/J9B,kBQgKwC;ATo/C5C;;ASnhDA;ERjII,eQkKqC;ATs/CzC;;ASvhDA;EAoCQ,UAAU;ATu/ClB;;AS3hDA;EA0CQ,UAAU;ATq/ClB;;AS/hDA;EA4CU,UAAU;ATu/CpB;;ASniDA;EA8CQ,YAAY;EACZ,cAAc;ATy/CtB;;ASxiDA;EAiDI,uBAAuB;AT2/C3B;;AS5iDA;EAoDQ,oBAAoB;EACpB,qBAAqB;AT4/C7B;;ASjjDA;EAuDI,yBAAyB;AT8/C7B;;ASrjDA;EA0DQ,oBAAoB;EACpB,qBAAqB;AT+/C7B;;AWl1DA;EACE,YAAY;EACZ,cAAc;EACd,kBAAkB;EAClB,WA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wB;EgBsCxB,WLsCU;AVovEhB;;Ae3zEA;EAgCM,yBhBvB4B;EgBwB5B,WLsCU;AVyvEhB;;Aeh0EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AV8uErE;;Aer0EA;EAgCM,yBhBrB4B;EgBsB5B,WLsCU;AVmwEhB;;Ae10EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVwvErE;;Ae/0EA;EAgCM,yBhBtB4B;EgBuB5B,WLsCU;AV6wEhB;;Aep1EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVkwErE;;Aez1EA;EAgCM,yBhBxB4B;EgByB5B,WLsCU;AVuxEhB;;Ae91EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AV4wErE;;Aen2EA;EAgCM,yBhBzB4B;EgB0B5B,yBLoCe;AVmyErB;;Aex2EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVsxErE;;Ae72EA;EAgCM,yBhBnB2B;EgBoB3B,WLsCU;AV2yEhB;;Ael3EA;EAuCU,yBLuCsC;EKtCtC,cL+C2D;AVgyErE;;AgBx3EA;EAEE,qBAAqB;EACrB,wBAAwB;EACxB,YAAY;EACZ,qBjBwDqB;EiBvDrB,cAAc;EACd,YjBoBW;EiBnBX,gBAAgB;EAChB,UAAU;EACV,WAAW;AhB03Eb;;AgBp4EA;EAYI,yBjBX2B;ACu4E/B;;AgBx4EA;EAcI,yBjBjB0B;AC+4E9B;;AgB54EA;EAgBI,yBjBnB0B;ACm5E9B;;AgBh5EA;EAkBI,yBjBrB0B;EiBsB1B,YAAY;AhBk4EhB;;AgBr5EA;EAyBQ,uBjBpBuB;ACo5E/B;;AgBz5EA;EA2BQ,uBjBtBuB;ACw5E/B;;AgB75EA;EA6BQ,uBjBxBuB;AC45E/B;;AgBj6EA;EA+BQ,mEAA2F;AhBs4EnG;;AgBr6EA;EAyBQ,yBjBjCqB;ACi7E7B;;AgBz6EA;EA2BQ,yBjBnCqB;ACq7E7B;;AgB76EA;EA6BQ,yBjBrCqB;ACy7E7B;;AgBj7EA;EA+BQ,qEAA2F;AhBs5EnG;;AgBr7EA;EAyBQ,4BjBtBsB;ACs7E9B;;AgBz7EA;EA2BQ,4BjBxBsB;AC07E9B;;AgB77EA;EA6BQ,4BjB1BsB;AC87E9B;;AgBj8EA;EA+BQ,wEAA2F;AhBs6EnG;;AgBr8EA;EAyBQ,yBjB7BsB;AC68E9B;;AgBz8EA;EA2BQ,yBjB/BsB;ACi9E9B;;AgB78EA;EA6BQ,yBjBjCsB;ACq9E9B;;AgBj9EA;EA+BQ,qEAA2F;AhBs7EnG;;AgBr9EA;EAyBQ,yBjBf0B;AC+8ElC;;AgBz9EA;EA2BQ,yBjBjB0B;ACm9ElC;;AgB79EA;EA6BQ,yBjBnB0B;ACu9ElC;;AgBj+EA;EA+BQ,qEAA2F;AhBs8EnG;;AgBr+EA;EAyBQ,yBjBb0B;AC69ElC;;AgBz+EA;EA2BQ,yBjBf0B;ACi+ElC;;AgB7+EA;EA6BQ,yBjBjB0B;ACq+ElC;;AgBj/EA;EA+BQ,qEAA2F;AhBs9EnG;;AgBr/EA;EAyBQ,yBjBd0B;AC8+ElC;;AgBz/EA;EA2BQ,yBjBhB0B;ACk/ElC;;AgB7/EA;EA6BQ,yBjBlB0B;ACs/ElC;;AgBjgFA;EA+BQ,qEAA2F;AhBs+EnG;;AgBrgFA;EAyBQ,yBjBhB0B;ACggFlC;;AgBzgFA;EA2BQ,yBjBlB0B;ACogFlC;;AgB7gFA;EA6BQ,yBjBpB0B;ACwgFlC;;AgBjhFA;EA+BQ,qEAA2F;AhBs/EnG;;AgBrhFA;EAyBQ,yBjBjB0B;ACihFlC;;AgBzhFA;EA2BQ,yBjBnB0B;ACqhFlC;;AgB7hFA;EA6BQ,yBjBrB0B;ACyhFlC;;AgBjiFA;EA+BQ,qEAA2F;AhBsgFnG;;AgBriFA;EAyBQ,yBjBXyB;AC2hFjC;;AgBziFA;EA2BQ,yBjBbyB;AC+hFjC;;AgB7iFA;EA6BQ,yBjBfyB;ACmiFjC;;AgBjjFA;EA+BQ,qEAA2F;AhBshFnG;;AgBrjFA;EAkCI,gCAtCkC;UAsClC,wBAtCkC;EAuClC,2CAAmC;UAAnC,mCAAmC;EACnC,yCAAiC;UAAjC,iCAAiC;EACjC,yCAAiC;UAAjC,iCAAiC;EACjC,yBjBrC2B;EiBsC3B,qEAA0F;EAC1F,6BAA6B;EAC7B,4BAA4B;EAC5B,0BAA0B;AhBuhF9B;;AgBjkFA;EA4CM,6BAA6B;AhByhFnC;;AgBrkFA;EA8CM,6BAA6B;AhB2hFnC;;AgBzkFA;EAgDM,oBAAoB;AhB6hF1B;;AgB7kFA;EAoDI,ejBxBY;ACqjFhB;;AgBjlFA;EAsDI,ejB5BY;AC2jFhB;;AgBrlFA;EAwDI,cjB/BW;ACgkFf;;AgB/hFA;EACE;IACE,2BAA2B;EhBkiF7B;EgBjiFA;IACE,4BAA4B;EhBmiF9B;AACF;;AgBxiFA;EACE;IACE,2BAA2B;EhBkiF7B;EgBjiFA;IACE,4BAA4B;EhBmiF9B;AACF;;AiB/kFA;EAEE,uBlBhB6B;EkBiB7B,clB1B4B;AC2mF9B;;AiBplFA;;EAMI,yBlBzB0B;EkB0B1B,qBA9B6B;EA+B7B,qBA9B6B;EA+B7B,mBAAmB;AjBmlFvB;;AiB5lFA;;EAeQ,uBlB7BuB;EkB8BvB,mBlB9BuB;EkB+BvB,clB5CqB;AC8nF7B;;AiBnmFA;;EAeQ,yBlB1CqB;EkB2CrB,qBlB3CqB;EkB4CrB,YlB/BuB;ACwnF/B;;AiB1mFA;;EAeQ,4BlB/BsB;EkBgCtB,wBlBhCsB;EkBiCtB,yBPkCa;AV8jFrB;;AiBjnFA;;EAeQ,yBlBtCsB;EkBuCtB,qBlBvCsB;EkBwCtB,WPoCQ;AVmkFhB;;AiBxnFA;;EAeQ,yBlBxB0B;EkByB1B,qBlBzB0B;EkB0B1B,WPoCQ;AV0kFhB;;AiB/nFA;;EAeQ,yBlBtB0B;EkBuB1B,qBlBvB0B;EkBwB1B,WPoCQ;AVilFhB;;AiBtoFA;;EAeQ,yBlBvB0B;EkBwB1B,qBlBxB0B;EkByB1B,WPoCQ;AVwlFhB;;AiB7oFA;;EAeQ,yBlBzB0B;EkB0B1B,qBlB1B0B;EkB2B1B,WPoCQ;AV+lFhB;;AiBppFA;;EAeQ,yBlB1B0B;EkB2B1B,qBlB3B0B;EkB4B1B,yBPkCa;AVwmFrB;;AiB3pFA;;EAeQ,yBlBpByB;EkBqBzB,qBlBrByB;EkBsBzB,WPoCQ;AV6mFhB;;AiBlqFA;;EAoBM,mBAAmB;EACnB,SAAS;AjBmpFf;;AiBxqFA;;EAuBM,yBlBhC4B;EkBiC5B,WP6BU;AVynFhB;;AiB9qFA;;;;EA2BQ,mBAAmB;AjB0pF3B;;AiBrrFA;;EA6BM,sBAAsB;AjB6pF5B;;AiB1rFA;EA+BI,clBtD0B;ACqtF9B;;AiB9rFA;EAiCM,mBAAmB;AjBiqFzB;;AiBlsFA;EAoCM,yBlB7C4B;EkB8C5B,WPgBU;AVkpFhB;;AiBvsFA;;EAwCQ,mBAAmB;AjBoqF3B;;AiB5sFA;;EA2CQ,kBPUQ;EOTR,mBAAmB;AjBsqF3B;;AiBltFA;EA8CI,6BA5DqC;AjBouFzC;;AiBttFA;;EAiDM,qBApEgC;EAqEhC,clBzEwB;ACmvF9B;;AiB5tFA;EAoDI,6BAhEqC;AjB4uFzC;;AiBhuFA;;EAuDM,qBAxEgC;EAyEhC,clB/EwB;AC6vF9B;;AiBtuFA;EA0DI,6BAvEqC;AjBuvFzC;;AiB1uFA;;EA+DU,sBAAsB;AjBgrFhC;;AiB/uFA;;EAoEM,iBAAiB;AjBgrFvB;;AiBpvFA;;EAyEU,wBAAwB;AjBgrFlC;;AiBzvFA;EA2EI,WAAW;AjBkrFf;;AiB7vFA;EAgFU,yBlB/FoB;ACgxF9B;;AiBjwFA;EAqFY,yBlBpGkB;ACoxF9B;;AiBrwFA;EAuFc,4BlBvGgB;ACyxF9B;;AiBzwFA;;EA2FM,qBAAqB;AjBmrF3B;;AiB9wFA;EAgGU,yBlB/GoB;ACiyF9B;;AiBhrFA;EhBjEE,iCAAiC;EgBoEjC,cAAc;EACd,kBAAkB;EAClB,eAAe;AjBkrFjB;;AkB7yFA;EACE,mBAAmB;EACnB,aAAa;EACb,eAAe;EACf,2BAA2B;AlBgzF7B;;AkBpzFA;EAMI,qBAAqB;AlBkzFzB;;AkBxzFA;EjBmJI,oBiB3IwC;AlBozF5C;;AkB5zFA;EAUI,sBAAsB;AlBszF1B;;AkBh0FA;EAYI,mBAAmB;AlBwzFvB;;AkBp0FA;EAgBM,enBYO;AC4yFb;;AkBx0FA;EAmBM,kBnBQU;ACizFhB;;AkB50FA;EAqBI,uBAAuB;AlB2zF3B;;AkBh1FA;EAuBM,qBAAqB;EACrB,oBAAoB;AlB6zF1B;;AkBr1FA;EA0BI,yBAAyB;AlB+zF7B;;AkBz1FA;EA6BQ,mBAAmB;AlBg0F3B;;AkB71FA;EA+BQ,eAAe;AlBk0FvB;;AkBj2FA;EjBmJI,eiBjHmC;AlBm0FvC;;AkBr2FA;EjBmJI,ciB/GqC;EAE/B,yBAAyB;EACzB,4BAA4B;AlBo0FtC;;AkB32FA;EA6CU,0BAA0B;EAC1B,6BAA6B;AlBk0FvC;;AkB7zFA;EACE,mBAAmB;EACnB,4BnBjD4B;EmBkD5B,kBnBMU;EmBLV,cnBzD4B;EmB0D5B,oBAAoB;EACpB,kBnB5Bc;EmB6Bd,WAAW;EACX,uBAAuB;EACvB,gBAAgB;EAChB,oBAAoB;EACpB,qBAAqB;EACrB,mBAAmB;AlBg0FrB;;AkB50FA;EjBgGI,oBiBlFuC;EjBkFvC,uBiBjFyC;AlBk0F7C;;AkBj1FA;EAqBM,uBnBlEyB;EmBmEzB,cnBhFuB;ACg5F7B;;AkBt1FA;EAqBM,yBnB/EuB;EmBgFvB,YnBnEyB;ACw4F/B;;AkB31FA;EAqBM,4BnBpEwB;EmBqExB,yBRFe;AV40FrB;;AkBh2FA;EAqBM,yBnB3EwB;EmB4ExB,WRAU;AV+0FhB;;AkBr2FA;EAqBM,yBnB7D4B;EmB8D5B,WRAU;AVo1FhB;;AkB12FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVy0FrE;;AkB/2FA;EAqBM,yBnB3D4B;EmB4D5B,WRAU;AV81FhB;;AkBp3FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVm1FrE;;AkBz3FA;EAqBM,yBnB5D4B;EmB6D5B,WRAU;AVw2FhB;;AkB93FA;EA4BU,yBRCsC;EQAtC,cRS2D;AV61FrE;;AkBn4FA;EAqBM,yBnB9D4B;EmB+D5B,WRAU;AVk3FhB;;AkBx4FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVu2FrE;;AkB74FA;EAqBM,yBnB/D4B;EmBgE5B,yBRFe;AV83FrB;;AkBl5FA;EA4BU,yBRCsC;EQAtC,cRS2D;AVi3FrE;;AkBv5FA;EAqBM,yBnBzD2B;EmB0D3B,WRAU;AVs4FhB;;AkB55FA;EA4BU,yBRCsC;EQAtC,cRS2D;AV23FrE;;AkBj6FA;EAgCI,kBnBtDY;AC27FhB;;AkBr6FA;EAkCI,enBzDS;ACg8Fb;;AkBz6FA;EAoCI,kBnB5DY;ACq8FhB;;AkB76FA;EjBgGI,qBiBzD0C;EjByD1C,sBiBxD0C;AlB04F9C;;AkBl7FA;EjBgGI,qBiBtD0C;EjBsD1C,sBiBrD0C;AlB44F9C;;AkBv7FA;EjBgGI,qBiBnD0C;EjBmD1C,sBiBlD0C;AlB84F9C;;AkB57FA;EjBgGI,gBiBvJmB;EAyGnB,UAAU;EACV,kBAAkB;EAClB,UAAU;AlB+4Fd;;AkBn8FA;EAuDM,8BAA8B;EAC9B,WAAW;EACX,cAAc;EACd,SAAS;EACT,kBAAkB;EAClB,QAAQ;EACR,0DAA0D;EAC1D,+BAA+B;AlBg5FrC;;AkB98FA;EAgEM,WAAW;EACX,UAAU;AlBk5FhB;;AkBn9FA;EAmEM,WAAW;EACX,UAAU;AlBo5FhB;;AkBx9FA;EAuEM,yBAAmD;AlBq5FzD;;AkB59FA;EAyEM,yBAAoD;AlBu5F1D;;AkBh+FA;EA2EI,qBnBhEmB;ACy9FvB;;AkBv5FA;EAEI,0BAA0B;AlBy5F9B;;AmB/gGA;;EAGE,sBAAsB;AnBihGxB;;AmBphGA;;;;EAMI,oBAAoB;AnBqhGxB;;AmB3hGA;;EAQI,iBApBmB;AnB4iGvB;;AmBhiGA;;EAUI,iBArBmB;AnBgjGvB;;AmBriGA;;EAYI,sBAAsB;AnB8hG1B;;AmB5hGA;EACE,cpB9B4B;EoBiC5B,epBLW;EoBMX,gBpBGmB;EoBFnB,kBAnCuB;AnBgkGzB;;AmBniGA;EAQI,cApCwB;EAqCxB,oBApCyB;AnBmkG7B;;AmBxiGA;EAWI,oBA3B+B;AnB4jGnC;;AmB5iGA;EAgBM,epBnBO;ACmjGb;;AmBhjGA;EAgBM,iBpBlBS;ACsjGf;;AmBpjGA;EAgBM,epBjBO;ACyjGb;;AmBxjGA;EAgBM,iBpBhBS;AC4jGf;;AmB5jGA;EAgBM,kBpBfU;AC+jGhB;;AmBhkGA;EAgBM,epBdO;ACkkGb;;AmBpkGA;EAgBM,kBpBbU;ACqkGhB;;AmBtjGA;EACE,cpB/C4B;EoBkD5B,kBpBrBc;EoBsBd,gBpBjBiB;EoBkBjB,iBA3CyB;AnBkmG3B;;AmB7jGA;EAQI,cpBvD0B;EoBwD1B,gBpBnBiB;AC4kGrB;;AmBlkGA;EAWI,oBA7C+B;AnBwmGnC;;AmBtkGA;EAgBM,epBrCO;AC+lGb;;AmB1kGA;EAgBM,iBpBpCS;ACkmGf;;AmB9kGA;EAgBM,epBnCO;ACqmGb;;AmBllGA;EAgBM,iBpBlCS;ACwmGf;;AmBtlGA;EAgBM,kBpBjCU;AC2mGhB;;AmB1lGA;EAgBM,epBhCO;AC8mGb;;AmB9lGA;EAgBM,kBpB/BU;ACinGhB;;AoB/oGA;EACE,cAAc;EACd,eAAe;EACf,mBAAmB;EACnB,kBAAkB;EAClB,yBAAyB;ApBkpG3B;;AoB7oGA;EACE,mBAAmB;EACnB,4BrBP4B;EqBQ5B,qBrBkDqB;EqBjDrB,oBAAoB;EACpB,kBrBac;EqBZd,WAAW;EACX,uBAAuB;EACvB,oBAAoB;EACpB,gBAAgB;EAChB,uBAAuB;EACvB,kBAAkB;EAClB,mBAAmB;ApBgpGrB;;AqB9qGA,eAAA;AC0DA;EAxBE,uBvBnB6B;EuBoB7B,qBvBzB4B;EuB0B5B,kBvBiCU;EuBhCV,cvB/B4B;ACgrG9B;;ACnnGI;EqB5BA,4BvBjC0B;ACorG9B;;ACvnGI;EqB5BA,4BvBjC0B;ACwrG9B;;AC3nGI;EqB5BA,4BvBjC0B;AC4rG9B;;AC/nGI;EqB5BA,4BvBjC0B;ACgsG9B;;AsB9pGE;EAEE,qBvBjC0B;ACisG9B;;AsB/pGE;EAIE,qBvBzB8B;EuB0B9B,iDvB1B8B;ACyrGlC;;AsB9pGE;;;;;EAEE,4BvBtC0B;EuBuC1B,wBvBvC0B;EuBwC1B,gBAAgB;EAChB,cvB9C0B;ACktG9B;;ACvpGI;;;;;EqBXE,+BvBhDwB;AC0tG9B;;AC/pGI;;;;;EqBXE,+BvBhDwB;ACkuG9B;;ACvqGI;;;;;EqBXE,+BvBhDwB;AC0uG9B;;AC/qGI;;;;;EqBXE,+BvBhDwB;ACkvG9B;;AuBpvGA;EAEE,2DxBN2B;EwBO3B,eAAe;EACf,WAAW;AvBsvGb;;AuBrvGE;EACE,gBAAgB;AvBwvGpB;;AuBpvGI;EACE,mBxBFyB;ACyvG/B;;AuBxvGK;EAMG,mDxBPuB;AC6vG/B;;AuB5vGI;EACE,qBxBfuB;AC8wG7B;;AuBhwGK;EAMG,gDxBpBqB;ACkxG7B;;AuBpwGI;EACE,wBxBJwB;AC2wG9B;;AuBxwGK;EAMG,mDxBTsB;AC+wG9B;;AuB5wGI;EACE,qBxBXwB;AC0xG9B;;AuBhxGK;EAMG,gDxBhBsB;AC8xG9B;;AuBpxGI;EACE,qBxBG4B;ACoxGlC;;AuBxxGK;EAMG,iDxBF0B;ACwxGlC;;AuB5xGI;EACE,qBxBK4B;AC0xGlC;;AuBhyGK;EAMG,iDxBA0B;AC8xGlC;;AuBpyGI;EACE,qBxBI4B;ACmyGlC;;AuBxyGK;EAMG,kDxBD0B;ACuyGlC;;AuB5yGI;EACE,qBxBE4B;AC6yGlC;;AuBhzGK;EAMG,kDxBH0B;ACizGlC;;AuBpzGI;EACE,qBxBC4B;ACszGlC;;AuBxzGK;EAMG,mDxBJ0B;AC0zGlC;;AuB5zGI;EACE,qBxBO2B;ACwzGjC;;AuBh0GK;EAMG,kDxBEyB;AC4zGjC;;AuB5zGE;EzBmBA,kBCyBgB;EDxBhB,kBCNc;ACmzGhB;;AuB/zGE;EzBoBA,kBCVc;ACyzGhB;;AuBj0GE;EzBoBA,iBCba;AC8zGf;;AuBl0GE;EACE,cAAc;EACd,WAAW;AvBq0Gf;;AuBp0GE;EACE,eAAe;EACf,WAAW;AvBu0Gf;;AuBr0GA;EAGI,qBxB8BmB;EwB7BnB,gDAA4D;EAC5D,iDAA6D;AvBs0GjE;;AuB30GA;EAOI,6BAA6B;EAC7B,yBAAyB;EACzB,gBAAgB;EAChB,eAAe;EACf,gBAAgB;AvBw0GpB;;AuBt0GA;EAEE,cAAc;EACd,eAAe;EACf,eAAe;EACf,2BzB7CkE;EyB8ClE,gBAAgB;AvBw0GlB;;AuB90GA;EAQI,gBA1DsB;EA2DtB,eA1DqB;AvBo4GzB;;AuBn1GA;EAWI,eAAe;AvB40GnB;;AuBv1GA;EAcI,YAAY;AvB60GhB;;AwB94GA;EACE,eAAe;EACf,qBAAqB;EACrB,iBAAiB;EACjB,kBAAkB;AxBi5GpB;;AwBh5GE;EACE,eAAe;AxBm5GnB;;AwBl5GE;EACE,czBF0B;ACu5G9B;;AwBp5GE;;;;;EAGE,czBJ0B;EyBK1B,mBAAmB;AxBy5GvB;;AwBp5GA;EvB0II,kBuBvIqC;AxBq5GzC;;AyBx6GA;EACE,qBAAqB;EACrB,eAAe;EACf,kBAAkB;EAClB,mBAAmB;AzB26GrB;;AyB/6GA;EAMI,a3BDkB;AE86GtB;;AyBn7GA;EAUM,qB1BU4B;EE8I9B,cwBvJ+B;EAC7B,UAAU;AzB66GhB;;AyBz7GA;EAeM,qB1BsDiB;EEqFnB,iBwB1IsC;AzB86G1C;;AyB97GA;EAmBI,eAAe;EACf,cAAc;EACd,cAAc;EACd,eAAe;EACf,aAAa;AzB+6GjB;;AyBt8GA;EAyBM,aAAa;AzBi7GnB;;AyB18GA;;EA4BM,wB1BjBwB;ACo8G9B;;AyB/8GA;ExB0JI,oBwB5HwC;AzBq7G5C;;AyBn9GA;EAgCM,YAAY;EACZ,UAAU;AzBu7GhB;;AyBx9GA;EAmCQ,kBAAkB;AzBy7G1B;;AyB59GA;EAuCM,qB1BnCwB;AC49G9B;;AyBh+GA;EA6CQ,mB1BhCuB;ACu9G/B;;AyBp+GA;EA+CQ,mB1BlCuB;AC29G/B;;AyBx+GA;EAkDU,qBfyDuB;AVi4GjC;;AyB5+GA;EAuDU,mD1B1CqB;ACm+G/B;;AyBh/GA;EA6CQ,qB1B7CqB;ACo/G7B;;AyBp/GA;EA+CQ,qB1B/CqB;ACw/G7B;;AyBx/GA;EAkDU,mBfyDuB;AVi5GjC;;AyB5/GA;EAuDU,gD1BvDmB;ACggH7B;;AyBhgHA;EA6CQ,wB1BlCsB;ACy/G9B;;AyBpgHA;EA+CQ,wB1BpCsB;AC6/G9B;;AyBxgHA;EAkDU,qBfyDuB;AVi6GjC;;AyB5gHA;EAuDU,mD1B5CoB;ACqgH9B;;AyBhhHA;EA6CQ,qB1BzCsB;ACghH9B;;AyBphHA;EA+CQ,qB1B3CsB;ACohH9B;;AyBxhHA;EAkDU,qBfyDuB;AVi7GjC;;AyB5hHA;EAuDU,gD1BnDoB;AC4hH9B;;AyBhiHA;EA6CQ,qB1B3B0B;ACkhHlC;;AyBpiHA;EA+CQ,qB1B7B0B;ACshHlC;;AyBxiHA;EAkDU,qBfyDuB;AVi8GjC;;AyB5iHA;EAuDU,iD1BrCwB;AC8hHlC;;AyBhjHA;EA6CQ,qB1BzB0B;ACgiHlC;;AyBpjHA;EA+CQ,qB1B3B0B;ACoiHlC;;AyBxjHA;EAkDU,qBfyDuB;AVi9GjC;;AyB5jHA;EAuDU,iD1BnCwB;AC4iHlC;;AyBhkHA;EA6CQ,qB1B1B0B;ACijHlC;;AyBpkHA;EA+CQ,qB1B5B0B;ACqjHlC;;AyBxkHA;EAkDU,qBfyDuB;AVi+GjC;;AyB5kHA;EAuDU,kD1BpCwB;AC6jHlC;;AyBhlHA;EA6CQ,qB1B5B0B;ACmkHlC;;AyBplHA;EA+CQ,qB1B9B0B;ACukHlC;;AyBxlHA;EAkDU,qBfyDuB;AVi/GjC;;AyB5lHA;EAuDU,kD1BtCwB;AC+kHlC;;AyBhmHA;EA6CQ,qB1B7B0B;AColHlC;;AyBpmHA;EA+CQ,qB1B/B0B;ACwlHlC;;AyBxmHA;EAkDU,qBfyDuB;AVigHjC;;AyB5mHA;EAuDU,mD1BvCwB;ACgmHlC;;AyBhnHA;EA6CQ,qB1BvByB;AC8lHjC;;AyBpnHA;EA+CQ,qB1BzByB;ACkmHjC;;AyBxnHA;EAkDU,qBfyDuB;AVihHjC;;AyB5nHA;EAuDU,kD1BjCuB;AC0mHjC;;AyBhoHA;E3ByCE,kBCyBgB;EDxBhB,kBCNc;ACimHhB;;AyBroHA;E3B4CE,kBCVc;ACumHhB;;AyBzoHA;E3B8CE,iBCba;AC4mHf;;AyB7oHA;EAkEM,qB1B5DwB;AC2oH9B;;AyBjpHA;EAoEI,WAAW;AzBilHf;;AyBrpHA;EAsEM,WAAW;AzBmlHjB;;AyBzpHA;EA0EM,aAAa;EACb,kBAAkB;ExBuFpB,cwBtF+B;EAC7B,YAAY;EACZ,eAAe;AzBmlHrB;;AyBjqHA;EAgFM,kB1B5CU;ACioHhB;;AyBrqHA;EAkFM,kB1BhDU;ACuoHhB;;AyBzqHA;EAoFM,iB1BnDS;AC4oHf;;A0BhqHA;EAEE,oBAAoB;EACpB,aAAa;EACb,2BAA2B;EAC3B,kBAAkB;A1BkqHpB;;A0BvqHA;EAYQ,uB3BZuB;E2BavB,yBAAyB;EACzB,c3B3BqB;AC0rH7B;;A0B7qHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,c3BjCmB;ACgsH7B;;A0BnrHA;EAwBU,yBAAyB;EACzB,+C3BzBqB;E2B0BrB,c3BvCmB;ACssH7B;;A0BzrHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,c3B7CmB;AC4sH7B;;A0B/rHA;EAYQ,yB3BzBqB;E2B0BrB,yBAAyB;EACzB,Y3BduB;ACqsH/B;;A0BrsHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,Y3BpBqB;AC2sH/B;;A0B3sHA;EAwBU,yBAAyB;EACzB,4C3BtCmB;E2BuCnB,Y3B1BqB;ACitH/B;;A0BjtHA;EA8BU,uBhBgEuB;EgB/DvB,yBAAyB;EACzB,Y3BhCqB;ACutH/B;;A0BvtHA;EAYQ,4B3BdsB;E2BetB,yBAAyB;EACzB,yBhBmDa;AV4pHrB;;A0B7tHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,yBhB6CW;AVkqHrB;;A0BnuHA;EAwBU,yBAAyB;EACzB,+C3B3BoB;E2B4BpB,yBhBuCW;AVwqHrB;;A0BzuHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,yBhBiCW;AV8qHrB;;A0B/uHA;EAYQ,yB3BrBsB;E2BsBtB,yBAAyB;EACzB,WhBqDQ;AVkrHhB;;A0BrvHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwrHhB;;A0B3vHA;EAwBU,yBAAyB;EACzB,4C3BlCoB;E2BmCpB,WhByCM;AV8rHhB;;A0BjwHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVosHhB;;A0BvwHA;EAYQ,yB3BP0B;E2BQ1B,yBAAyB;EACzB,WhBqDQ;AV0sHhB;;A0B7wHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVgtHhB;;A0BnxHA;EAwBU,yBAAyB;EACzB,6C3BpBwB;E2BqBxB,WhByCM;AVstHhB;;A0BzxHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AV4tHhB;;A0B/xHA;EAYQ,yB3BL0B;E2BM1B,yBAAyB;EACzB,WhBqDQ;AVkuHhB;;A0BryHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwuHhB;;A0B3yHA;EAwBU,yBAAyB;EACzB,6C3BlBwB;E2BmBxB,WhByCM;AV8uHhB;;A0BjzHA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVovHhB;;A0BvzHA;EAYQ,yB3BN0B;E2BO1B,yBAAyB;EACzB,WhBqDQ;AV0vHhB;;A0B7zHA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVgwHhB;;A0Bn0HA;EAwBU,yBAAyB;EACzB,8C3BnBwB;E2BoBxB,WhByCM;AVswHhB;;A0Bz0HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AV4wHhB;;A0B/0HA;EAYQ,yB3BR0B;E2BS1B,yBAAyB;EACzB,WhBqDQ;AVkxHhB;;A0Br1HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVwxHhB;;A0B31HA;EAwBU,yBAAyB;EACzB,8C3BrBwB;E2BsBxB,WhByCM;AV8xHhB;;A0Bj2HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVoyHhB;;A0Bv2HA;EAYQ,yB3BT0B;E2BU1B,yBAAyB;EACzB,yBhBmDa;AV4yHrB;;A0B72HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,yBhB6CW;AVkzHrB;;A0Bn3HA;EAwBU,yBAAyB;EACzB,+C3BtBwB;E2BuBxB,yBhBuCW;AVwzHrB;;A0Bz3HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,yBhBiCW;AV8zHrB;;A0B/3HA;EAYQ,yB3BHyB;E2BIzB,yBAAyB;EACzB,WhBqDQ;AVk0HhB;;A0Br4HA;EAkBU,yBhB4EuB;EgB3EvB,yBAAyB;EACzB,WhB+CM;AVw0HhB;;A0B34HA;EAwBU,yBAAyB;EACzB,8C3BhBuB;E2BiBvB,WhByCM;AV80HhB;;A0Bj5HA;EA8BU,yBhBgEuB;EgB/DvB,yBAAyB;EACzB,WhBmCM;AVo1HhB;;A0Bv5HA;EAmCI,kB3BZY;ACo4HhB;;A0B35HA;EAqCI,e3BfS;ACy4Hb;;A0B/5HA;EAuCI,kB3BlBY;AC84HhB;;A0Bn6HA;EA0CQ,eAAe;A1B63HvB;;A0Bv6HA;EA4CI,iB3BxBW;ACu5Hf;;A0B36HA;EA+CQ,eAAe;A1Bg4HvB;;A0B/6HA;EAmDM,6BAA6B;EAC7B,0BAA0B;A1Bg4HhC;;A0Bp7HA;EAsDM,4BAA4B;EAC5B,yBAAyB;A1Bk4H/B;;A0Bz7HA;EA0DQ,kB3BJI;ACu4HZ;;A0B77HA;EA4DQ,aAAa;A1Bq4HrB;;A0Bj8HA;EA+DM,sBAAsB;A1Bs4H5B;;A0Br8HA;EAiEM,sBAAsB;EACtB,YAAY;EACZ,gBAAgB;A1Bw4HtB;;A0B38HA;EAqEM,uBAAuB;A1B04H7B;;A0B/8HA;EAuEM,aAAa;EACb,YAAY;A1B44HlB;;A0Bp9HA;EA0EQ,eAAe;A1B84HvB;;A0Bx9HA;EA6EQ,eAAe;A1B+4HvB;;A0B59HA;EAgFQ,eAAe;A1Bg5HvB;;A0Bh+HA;EAmFQ,eAAe;A1Bi5HvB;;A0Bp+HA;EAsFQ,0BAA4C;A1Bk5HpD;;A0Bx+HA;EAwFQ,0B3BlCI;E2BmCJ,uBAAuB;A1Bo5H/B;;A0B7+HA;EA2FI,uBAAuB;A1Bs5H3B;;A0Bj/HA;EA8FM,WAAW;A1Bu5HjB;;A0Br/HA;EAgGM,YAAY;EACZ,eAAe;A1By5HrB;;A0B1/HA;EAmGI,yBAAyB;A1B25H7B;;A0B9/HA;EAqGM,0BAA4C;A1B65HlD;;A0BlgIA;EAuGM,0B3BjDM;E2BkDN,2BAA2B;EAC3B,SAAS;A1B+5Hf;;A0B75HA;EACE,oBAAoB;EACpB,aAAa;EACb,eAAe;EACf,2BAA2B;EAC3B,gBAAgB;EAChB,kBAAkB;A1Bg6HpB;;A0Bt6HA;EASM,yBhBtB2B;EgBuB3B,c3B9HwB;AC+hI9B;;A0B36HA;EAYM,qBhBzB2B;AV47HjC;;A0B/6HA;EAeM,yBhB5B2B;EgB6B3B,c3BpIwB;ACwiI9B;;A0Bp7HA;EAkBM,qBhB/B2B;AVq8HjC;;A0Bp6HA;EACE,YAAY;EACZ,OAAO;EACP,UAAU;EACV,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,WAAW;A1Bu6Hb;;A0Br6HA;;EAGE,qB3BhJ4B;E2BiJ5B,kB3BtFU;E2BuFV,cAAc;EACd,iBAAiB;EACjB,kBAAkB;EAClB,mBAAmB;A1Bu6HrB;;A0Br6HA;EACE,4B3BrJ4B;E2BsJ5B,c3B5J4B;ACokI9B;;A0Bt6HA;EACE,qB3B5J4B;E2B6J5B,mBA9J4B;EA+J5B,2BA9JoC;EA+JpC,cAAc;EACd,eA/JwB;EAgKxB,gBAAgB;EAChB,mBAAmB;EACnB,uBAAuB;A1By6HzB;;A0Bv6HA;EACE,mBAAmB;EACnB,aAAa;EACb,WAAW;EACX,uBAAuB;EzBvBrB,mByBwBmC;EACrC,UAAU;A1B06HZ;;A0Bh7HA;EAQI,eAAe;A1B46HnB;;A2B5lIA;EACE,c5BF4B;E4BG5B,cAAc;EACd,e5B2BW;E4B1BX,gB5BiCe;AC8jIjB;;A2BnmIA;EAMI,oBAAoB;A3BimIxB;;A2BvmIA;EASI,kB5BsBY;AC4kIhB;;A2B3mIA;EAWI,kB5BkBY;ACklIhB;;A2B/mIA;EAaI,iB5BeW;ACulIf;;A2BpmIA;EACE,cAAc;EACd,kB5Bcc;E4Bbd,mBAAmB;A3BumIrB;;A2B1mIA;EAOM,Y5BdyB;ACqnI/B;;A2B9mIA;EAOM,c5B3BuB;ACsoI7B;;A2BlnIA;EAOM,iB5BhBwB;AC+nI9B;;A2BtnIA;EAOM,c5BvBwB;AC0oI9B;;A2B1nIA;EAOM,c5BT4B;ACgoIlC;;A2B9nIA;EAOM,c5BP4B;ACkoIlC;;A2BloIA;EAOM,c5BR4B;ACuoIlC;;A2BtoIA;EAOM,c5BV4B;AC6oIlC;;A2B1oIA;EAOM,c5BX4B;ACkpIlC;;A2B9oIA;EAOM,c5BL2B;ACgpIjC;;A2BvoIA;EAEI,sBAAsB;A3ByoI1B;;A2B3oIA;EAKI,aAAa;EACb,2BAA2B;A3B0oI/B;;A2BhpIA;E1B2HI,kB0BlHwC;A3B2oI5C;;A2BppIA;;;EAcU,gBAAgB;A3B4oI1B;;A2B1pIA;;;EAoBY,6BAA6B;EAC7B,0BAA0B;A3B4oItC;;A2BjqIA;;;EA8BY,4BAA4B;EAC5B,yBAAyB;A3ByoIrC;;A2BxqIA;;;;;EAyCY,UAAU;A3BuoItB;;A2BhrIA;;;;;;;;;EA8CY,UAAU;A3B8oItB;;A2B5rIA;;;;;;;;;EAgDc,UAAU;A3BwpIxB;;A2BxsIA;EAkDQ,YAAY;EACZ,cAAc;A3B0pItB;;A2B7sIA;EAqDM,uBAAuB;A3B4pI7B;;A2BjtIA;EAuDM,yBAAyB;A3B8pI/B;;A2BrtIA;EA0DQ,YAAY;EACZ,cAAc;A3B+pItB;;A2B1tIA;EA6DI,aAAa;EACb,2BAA2B;A3BiqI/B;;A2B/tIA;EAgEM,cAAc;A3BmqIpB;;A2BnuIA;EAkEQ,gBAAgB;E1ByDpB,qB0BxD2C;A3BqqI/C;;A2BxuIA;EAqEQ,YAAY;EACZ,cAAc;A3BuqItB;;A2B7uIA;EAwEM,uBAAuB;A3ByqI7B;;A2BjvIA;EA0EM,yBAAyB;A3B2qI/B;;A2BrvIA;EA4EM,eAAe;A3B6qIrB;;A2BzvIA;EAgFU,sBAAsB;A3B6qIhC;;A2B7vIA;EAkFQ,uBAAuB;A3B+qI/B;;A2BjwIA;EAoFQ,gBAAgB;A3BirIxB;;ACrsIE;E0BhEF;IAuFM,aAAa;E3BmrIjB;AACF;;A2BlrIA;EAEI,kBAAkB;A3BorItB;;ACntIE;E0B6BF;IAII,qBAAqB;E3BurIvB;AACF;;ACrtIE;E0ByBF;IAMI,aAAa;IACb,YAAY;IACZ,cAAc;I1B0Bd,oB0BzBsC;IACtC,iBAAiB;E3B2rInB;E2BrsIF;IAYM,kB5BhGU;I4BiGV,oBAAoB;E3B4rIxB;E2BzsIF;IAeM,oBAAoB;E3B6rIxB;E2B5sIF;IAiBM,kB5BvGU;I4BwGV,oBAAoB;E3B8rIxB;E2BhtIF;IAoBM,iB5B3GS;I4B4GT,oBAAoB;E3B+rIxB;AACF;;A2B9rIA;EAEI,gBAAgB;A3BgsIpB;;AClvIE;E0BgDF;IAII,aAAa;IACb,aAAa;IACb,YAAY;IACZ,cAAc;E3BmsIhB;E2B1sIF;IASM,gBAAgB;E3BosIpB;E2B7sIF;IAWM,cAAc;E3BqsIlB;E2BhtIF;IAaQ,YAAY;E3BssIlB;E2BntIF;I1BWI,qB0BI2C;E3BusI7C;AACF;;A2BtsIA;EACE,sBAAsB;EACtB,WAAW;EACX,e5BhIW;E4BiIX,kBAAkB;EAClB,mBAAmB;A3BysIrB;;A2B9sIA;;;EAaU,c5BxKoB;AC+2I9B;;A2BptIA;;;EAeQ,kB5B3IQ;ACs1IhB;;A2B1tIA;;;EAiBQ,kB5B/IQ;AC81IhB;;A2BhuIA;;;EAmBQ,iB5BlJO;ACq2If;;A2BtuIA;EAqBM,c5B7KwB;E4B8KxB,a7BjLgB;E6BkLhB,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,Y7BrLgB;E6BsLhB,UAAU;A3BqtIhB;;A2BhvIA;;EA+BM,mB7B1LgB;AEg5ItB;;A2BrvIA;EAiCM,OAAO;A3BwtIb;;A2BzvIA;;EAqCM,oB7BhMgB;AEy5ItB;;A2B9vIA;EAuCM,QAAQ;A3B2tId;;A2BlwIA;EA2CM,6BAA6B;E1BzC/B,c0B0C+B;EAC7B,YAAY;EACZ,UAAU;A3B2tIhB;;A2BzwIA;EAgDM,kB5B5KU;ACy4IhB;;A2B7wIA;EAkDM,kB5BhLU;AC+4IhB;;A2BjxIA;EAoDM,iB5BnLS;ACo5If;;A4Bv7IA,qBAAA;ACWA;EAGE,e9BuBW;E8BtBX,mBAAmB;A7B86IrB;;A6Bl7IA;EAMI,mBAAmB;EACnB,c9BI8B;E8BH9B,aAAa;EACb,uBAAuB;EACvB,iBAduC;A7B87I3C;;A6B17IA;EAYM,c9BjBwB;ACm8I9B;;A6B97IA;EAcI,mBAAmB;EACnB,aAAa;A7Bo7IjB;;A6Bn8IA;E5BiJI,e4BhIoC;A7Bs7IxC;;A6Bv8IA;EAoBQ,c9BzBsB;E8B0BtB,eAAe;EACf,oBAAoB;A7Bu7I5B;;A6B78IA;EAwBM,c9B1BwB;E8B2BxB,iBAAiB;A7By7IvB;;A6Bl9IA;;EA4BI,uBAAuB;EACvB,aAAa;EACb,eAAe;EACf,2BAA2B;A7B27I/B;;A6B19IA;E5BiJI,mB4B/GuC;A7B47I3C;;A6B99IA;E5BiJI,kB4B7GuC;A7B87I3C;;A6Bl+IA;;EAyCM,uBAAuB;A7B87I7B;;A6Bv+IA;;EA6CM,yBAAyB;A7B+7I/B;;A6B5+IA;EAgDI,kB9BrBY;ACq9IhB;;A6Bh/IA;EAkDI,kB9BzBY;AC29IhB;;A6Bp/IA;EAoDI,iB9B5BW;ACg+If;;A6Bx/IA;EAwDM,iBAAiB;A7Bo8IvB;;A6B5/IA;EA2DM,iBAAiB;A7Bq8IvB;;A6BhgJA;EA8DM,iBAAiB;A7Bs8IvB;;A6BpgJA;EAiEM,iBAAiB;A7Bu8IvB;;A8B7/IA;EACE,uB/BR6B;E+BS7B,sBAnBmB;EAoBnB,0F/BvB2B;E+BwB3B,c/BnB4B;E+BoB5B,eAAe;EACf,kBAAkB;A9BggJpB;;A8B7/IE;EACE,+BA3BiB;EA4BjB,gCA5BiB;A9B4hJrB;;A8B//IE;EACE,kCA9BiB;EA+BjB,mCA/BiB;A9BiiJrB;;A8BhgJA;EAEE,6BAjCwC;EAkCxC,oBAAoB;EACpB,kD/BxC2B;E+ByC3B,aAAa;A9BkgJf;;A8BhgJA;EACE,mBAAmB;EACnB,c/BzC4B;E+B0C5B,aAAa;EACb,YAAY;EACZ,gB/BNe;E+BOf,qBA1CgC;A9B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;;AiCp0JA;EAgBQ,kBAlBsB;AjC00J9B;;AiCx0JA;EAkBI,8ClCnB0B;EkCoB1B,gBA1BgB;EA2BhB,iBA3BgB;AjCq1JpB;;AiC90JA;EAwBM,kBA9BsB;EA+BtB,mBA/BsB;AjCy1J5B;;AiCxzJA;;EAEE,gBAAgB;EAChB,YAAY;EACZ,cAAc;AjC2zJhB;;AiCzzJA;EhCgHI,kBgCxJgB;AjCq2JpB;;AiC1zJA;EhC6GI,iBgCxJgB;AjCy2JpB;;AiC3zJA;EACE,gBAAgB;EAChB,YAAY;EACZ,cAAc;EACd,mBAAmB;AjC8zJrB;;ACvxJE;EgC3CF;IAQI,gBAAgB;EjC+zJlB;AACF;;AkCt2JA;EACE,enCgBW;ACy1Jb;;AkC12JA;EAII,kBnCcY;AC41JhB;;AkC92JA;EAMI,kBnCUY;ACk2JhB;;AkCl3JA;EAQI,iBnCOW;ACu2Jf;;AkC52JA;EACE,iBArB0B;AlCo4J5B;;AkCh3JA;EAGI,kBnCmCc;EmClCd,cnC3B0B;EmC4B1B,cAAc;EACd,qBAzBiC;AlC04JrC;;AkCv3JA;EAQM,4BnCzBwB;EmC0BxB,cnCjCwB;ACo5J9B;;AkC53JA;EAYM,yBnCpB4B;EmCqB5B,WxBuCU;AV60JhB;;AkCj4JA;EjC8HI,8BFlJ0B;EmCqCxB,cAnC0B;EjCgJ5B,oBiC/IkC;AlCw5JtC;;AkCn3JA;EACE,cnC3C4B;EmC4C5B,iBApC2B;EAqC3B,qBApC+B;EAqC/B,yBAAyB;AlCs3J3B;;AkC13JA;EAMI,eAtCoB;AlC85JxB;;AkC93JA;EAQI,kBAxCoB;AlCk6JxB;;AmC75JA;EAEE,4BpCZ4B;EoCa5B,kBpC2CU;EoC1CV,epCUW;ACq5Jb;;AmCn6JA;EAMI,mBAAmB;AnCi6JvB;;AmCv6JA;EAQI,mBAAmB;EACnB,0BAA0B;AnCm6J9B;;AmC56JA;EAYI,kBpCGY;ACi6JhB;;AmCh7JA;EAcI,kBpCDY;ACu6JhB;;AmCp7JA;EAgBI,iBpCJW;AC46Jf;;AmCx7JA;EAsCM,uBAH+C;AnCy5JrD;;AmC57JA;EAwCQ,uBpChDuB;EoCiDvB,cpC9DqB;ACs9J7B;;AmCj8JA;EA2CQ,mBpCnDuB;AC68J/B;;AmCr8JA;EAsCM,yBAH+C;AnCs6JrD;;AmCz8JA;EAwCQ,yBpC7DqB;EoC8DrB,YpCjDuB;ACs9J/B;;AmC98JA;EA2CQ,qBpChEqB;ACu+J7B;;AmCl9JA;EAsCM,yBAH+C;AnCm7JrD;;AmCt9JA;EAwCQ,4BpClDsB;EoCmDtB,yBzBgBa;AVk6JrB;;AmC39JA;EA2CQ,wBpCrDsB;ACy+J9B;;AmC/9JA;EAsCM,yBAH+C;AnCg8JrD;;AmCn+JA;EAwCQ,yBpCzDsB;EoC0DtB,WzBkBQ;AV66JhB;;AmCx+JA;EA2CQ,qBpC5DsB;AC6/J9B;;AmC5+JA;EAsCM,yBzB4B0C;AV86JhD;;AmCh/JA;EAwCQ,yBpC3C0B;EoC4C1B,WzBkBQ;AV07JhB;;AmCr/JA;EA2CQ,qBpC9C0B;EoC+C1B,czB+B6D;AV+6JrE;;AmC1/JA;EAsCM,yBzB4B0C;AV47JhD;;AmC9/JA;EAwCQ,yBpCzC0B;EoC0C1B,WzBkBQ;AVw8JhB;;AmCngKA;EA2CQ,qBpC5C0B;EoC6C1B,czB+B6D;AV67JrE;;AmCxgKA;EAsCM,yBzB4B0C;AV08JhD;;AmC5gKA;EAwCQ,yBpC1C0B;EoC2C1B,WzBkBQ;AVs9JhB;;AmCjhKA;EA2CQ,qBpC7C0B;EoC8C1B,czB+B6D;AV28JrE;;AmCthKA;EAsCM,yBzB4B0C;AVw9JhD;;AmC1hKA;EAwCQ,yBpC5C0B;EoC6C1B,WzBkBQ;AVo+JhB;;AmC/hKA;EA2CQ,qBpC/C0B;EoCgD1B,czB+B6D;AVy9JrE;;AmCpiKA;EAsCM,yBzB4B0C;AVs+JhD;;AmCxiKA;EAwCQ,yBpC7C0B;EoC8C1B,yBzBgBa;AVo/JrB;;AmC7iKA;EA2CQ,qBpChD0B;EoCiD1B,czB+B6D;AVu+JrE;;AmCljKA;EAsCM,yBzB4B0C;AVo/JhD;;AmCtjKA;EAwCQ,yBpCvCyB;EoCwCzB,WzBkBQ;AVggKhB;;AmC3jKA;EA2CQ,qBpC1CyB;EoC2CzB,czB+B6D;AVq/JrE;;AmClhKA;EACE,mBAAmB;EACnB,yBpChE4B;EoCiE5B,0BAAgE;EAChE,WzBSc;EyBRd,aAAa;EACb,gBpC/Be;EoCgCf,8BAA8B;EAC9B,iBAAiB;EACjB,mBAtEiC;EAuEjC,kBAAkB;AnCqhKpB;;AmC/hKA;EAYI,YAAY;EACZ,cAAc;ElC0Ed,mBkCzEsC;AnCuhK1C;;AmCriKA;EAgBI,eAjEgC;EAkEhC,yBAAyB;EACzB,0BAA0B;AnCyhK9B;;AmCvhKA;EACE,qBpChF4B;EoCiF5B,kBpCtBU;EoCuBV,mBAAmB;EACnB,uBAjFmC;EAkFnC,cpCvF4B;EoCwF5B,qBAjFiC;AnC2mKnC;;AmChiKA;;EASI,uBpCnF2B;AC+mK/B;;AmCriKA;EAWI,6BAlFgD;AnCgnKpD;;AoChmKA;EAEE,mBAAmB;EACnB,aAAa;EACb,sBAAsB;EACtB,uBAAuB;EACvB,gBAAgB;EAChB,eAAe;EACf,WAxCU;ApC0oKZ;;AoC1mKA;EAWI,aAAa;ApCmmKjB;;AoCjmKA;EAEE,wCrC/C2B;ACkpK7B;;AoCjmKA;;EAEE,cA9CgC;EA+ChC,+BAA0D;EAC1D,cAAc;EACd,kBAAkB;EAClB,WAAW;ApComKb;;ACxkKE;EmClCF;;IASI,cAAc;IACd,8BAA0D;IAC1D,YAxDuB;EpC+pKzB;AACF;;AoCtmKA;EAEE,gBAAgB;EAChB,YAxD2B;EAyD3B,eAAe;EnCgGb,WmCxJoB;EA0DtB,SAzDoB;EA0DpB,WA5D2B;ApCoqK7B;;AoCtmKA;EACE,aAAa;EACb,sBAAsB;EACtB,8BAAgD;EAChD,gBAAgB;EAChB,uBAAuB;ApCymKzB;;AoCvmKA;;EAEE,mBAAmB;EACnB,4BrCtE4B;EqCuE5B,aAAa;EACb,cAAc;EACd,2BAA2B;EAC3B,aApE4B;EAqE5B,kBAAkB;ApC0mKpB;;AoCxmKA;EACE,gCrCjF4B;EqCkF5B,2BrCtBgB;EqCuBhB,4BrCvBgB;ACkoKlB;;AoCzmKA;EACE,crC1F4B;EqC2F5B,YAAY;EACZ,cAAc;EACd,iBrChEa;EqCiEb,cA7E8B;ApCyrKhC;;AoC1mKA;EACE,8BrCjCgB;EqCkChB,+BrClCgB;EqCmChB,6BrC/F4B;AC4sK9B;;AoChnKA;EnCsDI,mBmChDuC;ApC8mK3C;;AoC5mKA;EnChDE,iCAAiC;EmCkDjC,uBrCjG6B;EqCkG7B,YAAY;EACZ,cAAc;EACd,cAAc;EACd,aAtF4B;ApCqsK9B;;AqCzqKA;EACE,uBtC5C6B;EsC6C7B,mBAvDqB;EAwDrB,kBAAkB;EAClB,WAtDW;ArCkuKb;;AqChrKA;EASM,uBtCpDyB;EsCqDzB,ctClEuB;AC6uK7B;;AqCrrKA;;EAcU,ctCtEmB;ACkvK7B;;AqC1rKA;;;;EAoBY,yB3B+BqB;E2B9BrB,ctC7EiB;AC0vK7B;;AqClsKA;EAwBY,qBtChFiB;AC8vK7B;;AqCtsKA;EA0BQ,ctClFqB;ACkwK7B;;AC/qKE;EoC3BF;;;;IAgCY,ctCxFiB;EC0wK3B;EqCltKF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,ctC/Fe;ECuxK3B;EqC/tKF;;IA0Cc,qBtClGe;EC2xK3B;EqCnuKF;;;IA8CU,yB3BKuB;I2BJvB,ctCvGmB;ECiyK3B;EqCzuKF;IAmDc,uBtC9FiB;IsC+FjB,ctC5Ge;ECqyK3B;AACF;;AqC9uKA;EASM,yBtCjEuB;EsCkEvB,YtCrDyB;AC8xK/B;;AqCnvKA;;EAcU,YtCzDqB;ACmyK/B;;AqCxvKA;;;;EAoBY,uB3B+BqB;E2B9BrB,YtChEmB;AC2yK/B;;AqChwKA;EAwBY,mBtCnEmB;AC+yK/B;;AqCpwKA;EA0BQ,YtCrEuB;ACmzK/B;;AC7uKE;EoC3BF;;;;IAgCY,YtC3EmB;EC2zK7B;EqChxKF;;;;;;;;;;IAsCc,uB3BamB;I2BZnB,YtClFiB;ECw0K7B;EqC7xKF;;IA0Cc,mBtCrFiB;EC40K7B;EqCjyKF;;;IA8CU,uB3BKuB;I2BJvB,YtC1FqB;ECk1K7B;EqCvyKF;IAmDc,yBtC3Ge;IsC4Gf,YtC/FiB;ECs1K7B;AACF;;AqC5yKA;EASM,4BtCtDwB;EsCuDxB,yB3BYe;AV2xKrB;;AqCjzKA;;EAcU,yB3BQW;AVgyKrB;;AqCtzKA;;;;EAoBY,yB3B+BqB;E2B9BrB,yB3BCS;AVwyKrB;;AqC9zKA;EAwBY,gC3BFS;AV4yKrB;;AqCl0KA;EA0BQ,yB3BJa;AVgzKrB;;AC3yKE;EoC3BF;;;;IAgCY,yB3BVS;EVwzKnB;EqC90KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,yB3BjBO;EVq0KnB;EqC31KF;;IA0Cc,gC3BpBO;EVy0KnB;EqC/1KF;;;IA8CU,yB3BKuB;I2BJvB,yB3BzBW;EV+0KnB;EqCr2KF;IAmDc,4BtChGgB;IsCiGhB,yB3B9BO;EVm1KnB;AACF;;AqC12KA;EASM,yBtC7DwB;EsC8DxB,W3BcU;AVu1KhB;;AqC/2KA;;EAcU,W3BUM;AV41KhB;;AqCp3KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVo2KhB;;AqC53KA;EAwBY,kB3BAI;AVw2KhB;;AqCh4KA;EA0BQ,W3BFQ;AV42KhB;;ACz2KE;EoC3BF;;;;IAgCY,W3BRI;EVo3Kd;EqC54KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVi4Kd;EqCz5KF;;IA0Cc,kB3BlBE;EVq4Kd;EqC75KF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EV24Kd;EqCn6KF;IAmDc,yBtCvGgB;IsCwGhB,W3B5BE;EV+4Kd;AACF;;AqCx6KA;EASM,yBtC/C4B;EsCgD5B,W3BcU;AVq5KhB;;AqC76KA;;EAcU,W3BUM;AV05KhB;;AqCl7KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVk6KhB;;AqC17KA;EAwBY,kB3BAI;AVs6KhB;;AqC97KA;EA0BQ,W3BFQ;AV06KhB;;ACv6KE;EoC3BF;;;;IAgCY,W3BRI;EVk7Kd;EqC18KF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV+7Kd;EqCv9KF;;IA0Cc,kB3BlBE;EVm8Kd;EqC39KF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVy8Kd;EqCj+KF;IAmDc,yBtCzFoB;IsC0FpB,W3B5BE;EV68Kd;AACF;;AqCt+KA;EASM,yBtC7C4B;EsC8C5B,W3BcU;AVm9KhB;;AqC3+KA;;EAcU,W3BUM;AVw9KhB;;AqCh/KA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVg+KhB;;AqCx/KA;EAwBY,kB3BAI;AVo+KhB;;AqC5/KA;EA0BQ,W3BFQ;AVw+KhB;;ACr+KE;EoC3BF;;;;IAgCY,W3BRI;EVg/Kd;EqCxgLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV6/Kd;EqCrhLF;;IA0Cc,kB3BlBE;EVigLd;EqCzhLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVugLd;EqC/hLF;IAmDc,yBtCvFoB;IsCwFpB,W3B5BE;EV2gLd;AACF;;AqCpiLA;EASM,yBtC9C4B;EsC+C5B,W3BcU;AVihLhB;;AqCziLA;;EAcU,W3BUM;AVshLhB;;AqC9iLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AV8hLhB;;AqCtjLA;EAwBY,kB3BAI;AVkiLhB;;AqC1jLA;EA0BQ,W3BFQ;AVsiLhB;;ACniLE;EoC3BF;;;;IAgCY,W3BRI;EV8iLd;EqCtkLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EV2jLd;EqCnlLF;;IA0Cc,kB3BlBE;EV+jLd;EqCvlLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVqkLd;EqC7lLF;IAmDc,yBtCxFoB;IsCyFpB,W3B5BE;EVykLd;AACF;;AqClmLA;EASM,yBtChD4B;EsCiD5B,W3BcU;AV+kLhB;;AqCvmLA;;EAcU,W3BUM;AVolLhB;;AqC5mLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AV4lLhB;;AqCpnLA;EAwBY,kB3BAI;AVgmLhB;;AqCxnLA;EA0BQ,W3BFQ;AVomLhB;;ACjmLE;EoC3BF;;;;IAgCY,W3BRI;EV4mLd;EqCpoLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVynLd;EqCjpLF;;IA0Cc,kB3BlBE;EV6nLd;EqCrpLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EVmoLd;EqC3pLF;IAmDc,yBtC1FoB;IsC2FpB,W3B5BE;EVuoLd;AACF;;AqChqLA;EASM,yBtCjD4B;EsCkD5B,yB3BYe;AV+oLrB;;AqCrqLA;;EAcU,yB3BQW;AVopLrB;;AqC1qLA;;;;EAoBY,yB3B+BqB;E2B9BrB,yB3BCS;AV4pLrB;;AqClrLA;EAwBY,gC3BFS;AVgqLrB;;AqCtrLA;EA0BQ,yB3BJa;AVoqLrB;;AC/pLE;EoC3BF;;;;IAgCY,yB3BVS;EV4qLnB;EqClsLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,yB3BjBO;EVyrLnB;EqC/sLF;;IA0Cc,gC3BpBO;EV6rLnB;EqCntLF;;;IA8CU,yB3BKuB;I2BJvB,yB3BzBW;EVmsLnB;EqCztLF;IAmDc,yBtC3FoB;IsC4FpB,yB3B9BO;EVusLnB;AACF;;AqC9tLA;EASM,yBtC3C2B;EsC4C3B,W3BcU;AV2sLhB;;AqCnuLA;;EAcU,W3BUM;AVgtLhB;;AqCxuLA;;;;EAoBY,yB3B+BqB;E2B9BrB,W3BGI;AVwtLhB;;AqChvLA;EAwBY,kB3BAI;AV4tLhB;;AqCpvLA;EA0BQ,W3BFQ;AVguLhB;;AC7tLE;EoC3BF;;;;IAgCY,W3BRI;EVwuLd;EqChwLF;;;;;;;;;;IAsCc,yB3BamB;I2BZnB,W3BfE;EVqvLd;EqC7wLF;;IA0Cc,kB3BlBE;EVyvLd;EqCjxLF;;;IA8CU,yB3BKuB;I2BJvB,W3BvBM;EV+vLd;EqCvxLF;IAmDc,yBtCrFmB;IsCsFnB,W3B5BE;EVmwLd;AACF;;AqC5xLA;EAsDI,oBAAoB;EACpB,aAAa;EACb,mBA7GmB;EA8GnB,WAAW;ArC0uLf;;AqCnyLA;EA2DI,gCtCxG0B;ACo1L9B;;AqCvyLA;EALE,OAAO;EACP,eAAe;EACf,QAAQ;EACR,WA/CiB;ArC+1LnB;;AqC9yLA;EAgEI,SAAS;ArCkvLb;;AqClzLA;EAkEM,iCtC/GwB;ACm2L9B;;AqCtzLA;EAoEI,MAAM;ArCsvLV;;AqCpvLA;;EAGI,oBA9HmB;ArCo3LvB;;AqCzvLA;;EAKI,uBAhImB;ArCy3LvB;;AqCvvLA;;EAEE,oBAAoB;EACpB,aAAa;EACb,cAAc;EACd,mBAvIqB;ArCi4LvB;;AqCxvLA;EAIM,6BAA6B;ArCwvLnC;;AqCtvLA;EpCtFE,iCAAiC;EoCwFjC,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;ArCyvLpB;;AqCvvLA;EAEE,ctCrJ4B;EEoB5B,eAAe;EACf,cAAc;EACd,eoCxBqB;EpCyBrB,kBAAkB;EAClB,coC1BqB;EpCuJnB,iBoCEkC;ArC6vLtC;;AC33LE;EACE,8BAA8B;EAC9B,cAAc;EACd,WAAW;EACX,qBAAqB;EACrB,kBAAkB;EAClB,wBAAwB;EACxB,yBFiCQ;EEhCR,yDAAyD;EACzD,oCF0Ba;EEzBb,WAAW;AD83Lf;;AC73LI;EACE,oBAAoB;ADg4L1B;;AC/3LI;EACE,oBAAoB;ADk4L1B;;ACj4LI;EACE,oBAAoB;ADo4L1B;;ACn4LE;EACE,qCAAiC;ADs4LrC;;ACl4LM;EACE,wCAAwC;ADq4LhD;;ACp4LM;EACE,UAAU;ADu4LlB;;ACt4LM;EACE,0CAA0C;ADy4LlD;;AqCpyLA;EACE,aAAa;ArCuyLf;;AqCryLA;;EAEE,ctC9J4B;EsC+J5B,cAAc;EACd,gBAAgB;EAChB,uBAAuB;EACvB,kBAAkB;ArCwyLpB;;AqC9yLA;;EASM,qBAAqB;EACrB,sBAAsB;ArC0yL5B;;AqCxyLA;;EAEE,eAAe;ArC2yLjB;;AqC7yLA;;;;;EAOI,yBtCxK0B;EsCyK1B,ctCjK8B;AC+8LlC;;AqC5yLA;EACE,YAAY;EACZ,cAAc;ArC+yLhB;;AqCjzLA;EAII,mBA7KgC;ArC89LpC;;AqCrzLA;EAMI,UAAU;ArCmzLd;;AqCzzLA;EAQI,YAAY;EACZ,cAAc;ArCqzLlB;;AqC9zLA;EAWI,oCAAoC;EACpC,mBAhMmB;EAiMnB,kCAAkC;ArCuzLtC;;AqCp0LA;EAgBM,6BArLyC;EAsLzC,4BtCpL4B;AC4+LlC;;AqCz0LA;EAmBM,6BArL0C;EAsL1C,4BtCvL4B;EsCwL5B,0BArLuC;EAsLvC,wBArLqC;EAsLrC,ctC1L4B;EsC2L5B,kCAAwE;ArC0zL9E;;AqCxzLA;EACE,YAAY;EACZ,cAAc;ArC2zLhB;;AqCzzLA;EpC3DI,oBoC4DoC;ArC4zLxC;;AqC7zLA;EAII,qBtCrM8B;EsCsM9B,oBAAoB;EpCxDpB,coCyD6B;ArC6zLjC;;AqC3zLA;EACE,mBAAmB;EACnB,sBAAsB;EACtB,mBAAmB;ArC8zLrB;;AqCj0LA;EAKI,oBAAoB;EACpB,qBAAqB;ArCg0LzB;;AqC9zLA;EACE,4BtC3N4B;EsC4N5B,YAAY;EACZ,aAAa;EACb,WA/LyB;EAgMzB,gBAAgB;ArCi0LlB;;ACp9LE;EoC/BF;IAsLI,cAAc;ErCk0LhB;EqCj0LA;;IAGI,mBAAmB;IACnB,aAAa;ErCk0LjB;EqCj0LA;IAEI,aAAa;ErCk0LjB;EqC15LF;IA0FI,uBtC3O2B;IsC4O3B,4CtCzPyB;IsC0PzB,iBAAiB;ErCm0LnB;EqCt0LA;IAKI,cAAc;ErCo0LlB;EqCl0LA;IA3MA,OAAO;IACP,eAAe;IACf,QAAQ;IACR,WA/CiB;ErC+jMjB;EqCx0LA;IAKI,SAAS;ErCs0Lb;EqC30LA;IAOM,4CtCrQqB;EC4kM3B;EqC90LA;IASI,MAAM;ErCw0LV;EqCj1LA;IpClMA,iCAAiC;IoCgN3B,iCAA2C;IAC3C,cAAc;ErCu0LpB;EqCt0LA;;IAGI,oBA9QiB;ErCqlMrB;EqC10LA;;IAKI,uBAhRiB;ErCylMrB;AACF;;AC1gME;EoCmMA;;;;IAIE,oBAAoB;IACpB,aAAa;ErC20Lf;EqC9iMF;IAqOI,mBA1RmB;ErCsmMrB;EqC70LA;IAGI,kBA1R0B;ErCumM9B;EqCh1LA;;IAMM,mBAAmB;ErC80LzB;EqCp1LA;;IASM,kBtClOI;ECijMV;EqCx1LA;;;;IAgBQ,wCAAwC;ErC80LhD;EqC91LA;IAuBU,wCAAwC;ErC00LlD;EqCj2LA;IA4BU,4BtC7SkB;IsC8SlB,ctCzTiB;ECioM3B;EqCr2LA;IA+BU,4BtChTkB;IsCiTlB,ctCxSsB;ECinMhC;EqC7+LF;IAsKI,aAAa;ErC00Lf;EqCv+LF;;IAgKI,mBAAmB;IACnB,aAAa;ErC20Lf;EqCt9LF;IA8IM,oBAAoB;ErC20LxB;EqC70LA;IAKM,oDAAoD;ErC20L1D;EqCh1LA;IAOM,gCtClUsB;IsCmUtB,0BAAkE;IAClE,gBAAgB;IAChB,YAAY;IACZ,4CtC9UqB;IsC+UrB,SAAS;ErC40Lf;EqCx1LA;IAkBM,cAAc;ErCy0LpB;EqCx0LM;IAEE,UAAU;IACV,oBAAoB;IACpB,wBAAwB;ErCy0LhC;EqCrgMF;IA8LI,YAAY;IACZ,cAAc;ErC00LhB;EqCz0LA;IACE,2BAA2B;IpCrM3B,kBoCsMoC;ErC20LtC;EqC10LA;IACE,yBAAyB;IpCxMzB,iBoCyMoC;ErC40LtC;EqCl9LF;IAwII,uBtCxV2B;IsCyV3B,8BtClSc;IsCmSd,+BtCnSc;IsCoSd,6BtChW0B;IsCiW1B,2CtCzWyB;IsC0WzB,aAAa;IACb,mBAAmB;IpCzMnB,OoC0MuB;IACvB,eAAe;IACf,kBAAkB;IAClB,SAAS;IACT,WAjVkB;ErC8pMpB;EqCh+LF;IAqJM,sBAAsB;IACtB,mBAAmB;ErC80LvB;EqC71LA;IpC1ME,mBoC2NuC;ErC+0LzC;EqCh2LA;IAoBM,4BtC7WsB;IsC8WtB,ctCzXqB;ECwsM3B;EqCp2LA;IAuBM,4BtChXsB;IsCiXtB,ctCxW0B;ECwrMhC;EqC/0LE;IAEE,kBtC3TY;IsC4TZ,gBAAgB;IAChB,4EtCjYuB;IsCkYvB,cAAc;IACd,UAAU;IACV,oBAAoB;IACpB,wBAA8C;IAC9C,2BAA2B;IAC3B,yBtCjUM;IsCkUN,uCAAuC;ErCg1L3C;EqCp3LA;IAsCI,UAAU;IACV,QAAQ;ErCi1LZ;EqCv/LF;IAwKI,cAAc;ErCk1LhB;EqCj1LA;;IpCpPE,qBoCuPyC;ErCk1L3C;EqCr1LA;;IpCpPE,sBoCyPyC;ErCo1L3C;EqCl1LA;IAlWA,OAAO;IACP,eAAe;IACf,QAAQ;IACR,WA/CiB;ErCsuMjB;EqCx1LA;IAKI,SAAS;ErCs1Lb;EqC31LA;IAOM,4CtC5ZqB;ECmvM3B;EqC91LA;IASI,MAAM;ErCw1LV;EqCv1LA;;IAGI,oBA/ZiB;ErCuvMrB;EqC31LA;;IAKI,uBAjaiB;ErC2vMrB;EqC/1LA;;IAOI,oBAA4D;ErC41LhE;EqCn2LA;;IASI,uBAA+D;ErC81LnE;EqC51LA;;IAGI,ctC7auB;EC0wM3B;EqCh2LA;;IAKI,6BAla2C;ErCiwM/C;EqC91LA;IAKM,yBtCzasB;ECqwM5B;AACF;;AqCz1LA;EAEI,iCAA2C;ArC21L/C;;AsCnvMA;EAEE,evCFW;EuCGX,gBAnC0B;AtCwxM5B;;AsCxvMA;EAMI,kBvCLY;AC2vMhB;;AsC5vMA;EAQI,kBvCTY;ACiwMhB;;AsChwMA;EAUI,iBvCZW;ACswMf;;AsCpwMA;;EAcM,iBAAiB;EACjB,kBAAkB;EAClB,qBvCkBiB;ACyuMvB;;AsC3wMA;EAkBM,qBvCgBiB;AC6uMvB;;AsC3vMA;;EAEE,mBAAmB;EACnB,aAAa;EACb,uBAAuB;EACvB,kBAAkB;AtC8vMpB;;AsC5vMA;;;;EAME,cA9D6B;EA+D7B,uBAAuB;EACvB,eA/D8B;EAgE9B,mBA/DkC;EAgElC,oBA/DmC;EAgEnC,kBAAkB;AtC6vMpB;;AsC3vMA;;;EAGE,qBvCtE4B;EuCuE5B,cvC3E4B;EuC4E5B,gBxC3EoB;AEy0MtB;;AsCnwMA;;;EAOI,qBvC3E0B;EuC4E1B,cvC/E0B;ACi1M9B;;AsC1wMA;;;EAUI,qBvCjE8B;ACu0MlC;;AsChxMA;;;EAYI,iDvCvFyB;ACi2M7B;;AsCtxMA;;;EAcI,yBvCjF0B;EuCkF1B,qBvClF0B;EuCmF1B,gBAAgB;EAChB,cvCtF0B;EuCuF1B,YAAY;AtC8wMhB;;AsC5wMA;;EAEE,oBAtFkC;EAuFlC,qBAtFmC;EAuFnC,mBAAmB;AtC+wMrB;;AsC7wMA;EAEI,yBvCnF8B;EuCoF9B,qBvCpF8B;EuCqF9B,W5BzBY;AVwyMhB;;AsC7wMA;EACE,cvCrG4B;EuCsG5B,oBAAoB;AtCgxMtB;;AsC9wMA;EACE,eAAe;AtCixMjB;;AsClxMA;EAGI,gBAAgB;AtCmxMpB;;AC1yME;EqCxDF;IAmFI,eAAe;EtCoxMjB;EsC3yMF;;IA0BI,YAAY;IACZ,cAAc;EtCqxMhB;EsChyMF;IAcM,YAAY;IACZ,cAAc;EtCqxMlB;AACF;;ACrzME;EqCgBF;IAmBI,YAAY;IACZ,cAAc;IACd,2BAA2B;IAC3B,QAAQ;EtCuxMV;EsC91MF;;;;IA4EI,gBAAgB;IAChB,aAAa;EtCwxMf;EsCvxMA;IACE,QAAQ;EtCyxMV;EsCxxMA;IACE,QAAQ;EtC0xMV;EsCt4MF;IA8GI,8BAA8B;IAC9B,gBAAgB;IAChB,aAAa;EtC2xMf;EsC9xMA;IAMM,QAAQ;EtC2xMd;EsCjyMA;IAQM,uBAAuB;IACvB,QAAQ;EtC4xMd;EsCryMA;IAWM,QAAQ;EtC6xMd;EsCxyMA;IAcM,QAAQ;EtC6xMd;EsC3yMA;IAgBM,QAAQ;EtC8xMd;EsC9yMA;IAkBM,yBAAyB;IACzB,QAAQ;EtC+xMd;AACF;;AuCr6MA;EACE,kBxCqCgB;EwCpChB,0FxChC2B;EwCiC3B,exCEW;ACs6Mb;;AuC36MA;EAKI,qBxCWkB;AC+5MtB;;AuC/6MA;EAYQ,uBxC7BuB;EwC8BvB,cxC3CqB;ACk9M7B;;AuCp7MA;EAeQ,0BxChCuB;ACy8M/B;;AuCx7MA;EAiBQ,YxClCuB;AC68M/B;;AuC57MA;EAYQ,yBxC1CqB;EwC2CrB,YxC9BuB;ACk9M/B;;AuCj8MA;EAeQ,4BxC7CqB;ACm+M7B;;AuCr8MA;EAiBQ,cxC/CqB;ACu+M7B;;AuCz8MA;EAYQ,4BxC/BsB;EwCgCtB,yB7BmCa;AV85MrB;;AuC98MA;EAeQ,+BxClCsB;ACq+M9B;;AuCl9MA;EAiBQ,iBxCpCsB;ACy+M9B;;AuCt9MA;EAYQ,yBxCtCsB;EwCuCtB,W7BqCQ;AVy6MhB;;AuC39MA;EAeQ,4BxCzCsB;ACy/M9B;;AuC/9MA;EAiBQ,cxC3CsB;AC6/M9B;;AuCn+MA;EAYQ,yBxCxB0B;EwCyB1B,W7BqCQ;AVs7MhB;;AuCx+MA;EAeQ,4BxC3B0B;ACw/MlC;;AuC5+MA;EAiBQ,cxC7B0B;AC4/MlC;;AuCh/MA;EAYQ,yBxCtB0B;EwCuB1B,W7BqCQ;AVm8MhB;;AuCr/MA;EAeQ,4BxCzB0B;ACmgNlC;;AuCz/MA;EAiBQ,cxC3B0B;ACugNlC;;AuC7/MA;EAYQ,yBxCvB0B;EwCwB1B,W7BqCQ;AVg9MhB;;AuClgNA;EAeQ,4BxC1B0B;ACihNlC;;AuCtgNA;EAiBQ,cxC5B0B;ACqhNlC;;AuC1gNA;EAYQ,yBxCzB0B;EwC0B1B,W7BqCQ;AV69MhB;;AuC/gNA;EAeQ,4BxC5B0B;ACgiNlC;;AuCnhNA;EAiBQ,cxC9B0B;ACoiNlC;;AuCvhNA;EAYQ,yBxC1B0B;EwC2B1B,yB7BmCa;AV4+MrB;;AuC5hNA;EAeQ,4BxC7B0B;AC8iNlC;;AuChiNA;EAiBQ,cxC/B0B;ACkjNlC;;AuCpiNA;EAYQ,yBxCpByB;EwCqBzB,W7BqCQ;AVu/MhB;;AuCziNA;EAeQ,4BxCvByB;ACqjNjC;;AuC7iNA;EAiBQ,cxCzByB;ACyjNjC;;AuC9hNA;;EAGI,gCxC3C2B;AC2kN/B;;AuC9hNA;EACE,yBxC9C6B;EwC+C7B,0BAA8C;EAC9C,cxCrD4B;EwCsD5B,iBAhDyB;EAiDzB,gBxCjBe;EwCkBf,iBArD8B;EAsD9B,mBArDgC;AvCslNlC;;AuC/hNA;EACE,qBAAqB;EACrB,aAAa;EACb,kBArD4B;EAsD5B,uBAAuB;AvCkiNzB;;AuCtiNA;EAMI,gCxC7D0B;EwC8D1B,mBAAmB;EACnB,cAAc;AvCoiNlB;;AuC5iNA;EAWM,4BxCrEwB;EwCsExB,cxCvEwB;AC4mN9B;;AuCniNA;EAEI,cxC1E0B;AC+mN9B;;AuCviNA;EAIM,cxC7D4B;AComNlC;;AuCriNA;EACE,mBAAmB;EACnB,cxCjF4B;EwCkF5B,aAAa;EACb,2BAA2B;EAC3B,qBAAqB;AvCwiNvB;;AuC7iNA;EtCuEI,oBsChEsC;AvC0iN1C;;AuCjjNA;EASI,YAAY;EACZ,cAAc;EACd,WAAW;AvC4iNf;;AuCvjNA;EAaI,eAAe;AvC8iNnB;;AuC3jNA;EAeI,0BxC9E8B;EwC+E9B,cxC/F0B;AC+oN9B;;AuChkNA;EAkBM,cxCjF4B;ACmoNlC;;AuCpkNA;EAoBI,8BxCnCc;EwCoCd,+BxCpCc;ACwlNlB;;AuCljNA;;EAEE,eAAe;AvCqjNjB;;AuCvjNA;;EAII,4BxCnG0B;AC2pN9B;;AuCtjNA;EtChGE,qBAAqB;EACrB,esCgGgB;EtC/FhB,WsC+FqB;EtC9FrB,gBsC8FqB;EtC7FrB,kBAAkB;EAClB,mBAAmB;EACnB,UsC2FqB;EACrB,cxC5G4B;EEoJ1B,oBsCvCoC;AvC+jNxC;;AuClkNA;EAKI,kBAAkB;EAClB,oBAAoB;AvCikNxB;;AwC3pNA;EvCgCE,iCAAiC;EuC5BjC,oBAAoB;EACpB,aAAa;EACb,ezCCW;EyCAX,8BAA8B;EAC9B,gBAAgB;EAChB,gBAAgB;EAChB,mBAAmB;AxC4pNrB;;AwCtqNA;EAYI,mBAAmB;EACnB,4BzCjC0B;EyCkC1B,0BAzC4B;EA0C5B,wBAzC0B;EA0C1B,czCvC0B;EyCwC1B,aAAa;EACb,uBAAuB;EACvB,mBAA6C;EAC7C,kBAxCyB;EAyCzB,mBAAmB;AxC8pNvB;;AwCnrNA;EAuBM,4BzC/CwB;EyCgDxB,czChDwB;ACgtN9B;;AwCxrNA;EA0BI,cAAc;AxCkqNlB;;AwC5rNA;EA6BQ,4BzCrC0B;EyCsC1B,czCtC0B;ACysNlC;;AwCjsNA;EAgCI,mBAAmB;EACnB,4BzCrD0B;EyCsD1B,0BA7D4B;EA8D5B,wBA7D0B;EA8D1B,aAAa;EACb,YAAY;EACZ,cAAc;EACd,2BAA2B;AxCqqN/B;;AwC5sNA;EAyCM,qBAAqB;AxCuqN3B;;AwChtNA;EA2CM,UAAU;EACV,uBAAuB;EACvB,oBAAoB;EACpB,qBAAqB;AxCyqN3B;;AwCvtNA;EAgDM,yBAAyB;EACzB,oBAAoB;AxC2qN1B;;AwC5tNA;EvC8HI,mBuC1EuC;AxC4qN3C;;AwChuNA;EvC8HI,kBuCxEuC;AxC8qN3C;;AwCpuNA;EA0DM,uBAAuB;AxC8qN7B;;AwCxuNA;EA6DM,yBAAyB;AxC+qN/B;;AwC5uNA;EAiEM,6BAA6B;EAE3B,0BAAkE;AxC8qN1E;;AwCjvNA;EAuEQ,4BzCxFsB;EyCyFtB,4BzC5FsB;AC0wN9B;;AwCtvNA;EA4EU,uBzC3FqB;EyC4FrB,qBzCjGoB;EyCkGpB,2CAA2E;AxC8qNrF;;AwC5vNA;EAiFM,YAAY;EACZ,cAAc;AxC+qNpB;;AwCjwNA;EAqFM,qBzCzGwB;EyC0GxB,mBA/F+B;EAgG/B,iBA/F6B;EAgG7B,gBAAgB;EAChB,kBAAkB;AxCgrNxB;;AwCzwNA;EA2FQ,4BzC5GsB;EyC6GtB,qBzCjHsB;EyCkHtB,UAAU;AxCkrNlB;;AwC/wNA;EvC8HI,iBuC9BuE;AxCmrN3E;;AwCnxNA;EAmGU,2BzC5DE;EyC6DF,8BzC7DE;ACivNZ;;AwCxxNA;EA0GU,4BzCnEE;EyCoEF,+BzCpEE;ACsvNZ;;AwC7xNA;EAiHU,yBzCzHwB;EyC0HxB,qBzC1HwB;EyC2HxB,W9B/DM;E8BgEN,UAAU;AxCgrNpB;;AwCpyNA;EAsHM,mBAAmB;AxCkrNzB;;AwCxyNA;EA2HY,iCzClFW;EyCmFX,8BzCnFW;EyCoFX,oBAAoB;AxCirNhC;;AwC9yNA;EAoIY,kCzC3FW;EyC4FX,+BzC5FW;EyC6FX,qBAAqB;AxC8qNjC;;AwCpzNA;EA6II,kBzCrIY;ACgzNhB;;AwCxzNA;EA+II,kBzCzIY;ACszNhB;;AwC5zNA;EAiJI,iBzC5IW;AC2zNf;;AyC91NA,eAAA;ACIA;EACE,cAAc;EACd,aAAa;EACb,YAAY;EACZ,cAAc;EACd,gBAPkB;A1Cq2NpB;;A0C71NE;EACE,UAAU;EACV,YAAY;A1Cg2NhB;;A0C/1NE;EACE,UAAU;EACV,WAAW;A1Ck2Nf;;A0Cj2NE;EACE,UAAU;EACV,UAAU;A1Co2Nd;;A0Cn2NE;EACE,UAAU;EACV,eAAe;A1Cs2NnB;;A0Cr2NE;EACE,UAAU;EACV,UAAU;A1Cw2Nd;;A0Cv2NE;EACE,UAAU;EACV,eAAe;A1C02NnB;;A0Cz2NE;EACE,UAAU;EACV,UAAU;A1C42Nd;;A0C32NE;EACE,UAAU;EACV,UAAU;A1C82Nd;;A0C72NE;EACE,UAAU;EACV,UAAU;A1Cg3Nd;;A0C/2NE;EACE,UAAU;EACV,UAAU;A1Ck3Nd;;A0Cj3NE;EACE,UAAU;EACV,UAAU;A1Co3Nd;;A0Cn3NE;EzCiHE,gByChHmC;A1Cs3NvC;;A0Cr3NE;EzC+GE,qByC9GwC;A1Cw3N5C;;A0Cv3NE;EzC6GE,gByC5GmC;A1C03NvC;;A0Cz3NE;EzC2GE,qByC1GwC;A1C43N5C;;A0C33NE;EzCyGE,gByCxGmC;A1C83NvC;;A0C73NE;EzCuGE,gByCtGmC;A1Cg4NvC;;A0C/3NE;EzCqGE,gByCpGmC;A1Ck4NvC;;A0Cj4NE;EzCmGE,gByClGmC;A1Co4NvC;;A0Cn4NE;EzCiGE,gByChGmC;A1Cs4NvC;;A0Cp4NI;EACE,UAAU;EACV,SAAiC;A1Cu4NvC;;A0Ct4NI;EzC2FA,eyC1F4D;A1Cy4NhE;;A0C74NI;EACE,UAAU;EACV,eAAiC;A1Cg5NvC;;A0C/4NI;EzC2FA,qByC1F4D;A1Ck5NhE;;A0Ct5NI;EACE,UAAU;EACV,gBAAiC;A1Cy5NvC;;A0Cx5NI;EzC2FA,sByC1F4D;A1C25NhE;;A0C/5NI;EACE,UAAU;EACV,UAAiC;A1Ck6NvC;;A0Cj6NI;EzC2FA,gByC1F4D;A1Co6NhE;;A0Cx6NI;EACE,UAAU;EACV,gBAAiC;A1C26NvC;;A0C16NI;EzC2FA,sByC1F4D;A1C66NhE;;A0Cj7NI;EACE,UAAU;EACV,gBAAiC;A1Co7NvC;;A0Cn7NI;EzC2FA,sByC1F4D;A1Cs7NhE;;A0C17NI;EACE,UAAU;EACV,UAAiC;A1C67NvC;;A0C57NI;EzC2FA,gByC1F4D;A1C+7NhE;;A0Cn8NI;EACE,UAAU;EACV,gBAAiC;A1Cs8NvC;;A0Cr8NI;EzC2FA,sByC1F4D;A1Cw8NhE;;A0C58NI;EACE,UAAU;EACV,gBAAiC;A1C+8NvC;;A0C98NI;EzC2FA,sByC1F4D;A1Ci9NhE;;A0Cr9NI;EACE,UAAU;EACV,UAAiC;A1Cw9NvC;;A0Cv9NI;EzC2FA,gByC1F4D;A1C09NhE;;A0C99NI;EACE,UAAU;EACV,gBAAiC;A1Ci+NvC;;A0Ch+NI;EzC2FA,sByC1F4D;A1Cm+NhE;;A0Cv+NI;EACE,UAAU;EACV,gBAAiC;A1C0+NvC;;A0Cz+NI;EzC2FA,sByC1F4D;A1C4+NhE;;A0Ch/NI;EACE,UAAU;EACV,WAAiC;A1Cm/NvC;;A0Cl/NI;EzC2FA,iByC1F4D;A1Cq/NhE;;AC19NE;EyCzFF;IAiEM,UAAU;IACV,YAAY;E1Cu/NhB;E0CzjOF;IAoEM,UAAU;IACV,WAAW;E1Cw/Nf;E0C7jOF;IAuEM,UAAU;IACV,UAAU;E1Cy/Nd;E0CjkOF;IA0EM,UAAU;IACV,eAAe;E1C0/NnB;E0CrkOF;IA6EM,UAAU;IACV,UAAU;E1C2/Nd;E0CzkOF;IAgFM,UAAU;IACV,eAAe;E1C4/NnB;E0C7kOF;IAmFM,UAAU;IACV,UAAU;E1C6/Nd;E0CjlOF;IAsFM,UAAU;IACV,UAAU;E1C8/Nd;E0CrlOF;IAyFM,UAAU;IACV,UAAU;E1C+/Nd;E0CzlOF;IA4FM,UAAU;IACV,UAAU;E1CggOd;E0C7lOF;IA+FM,UAAU;IACV,UAAU;E1CigOd;E0CjmOF;IzCwJI,gByCtDqC;E1CkgOvC;E0CpmOF;IzCwJI,qByCpD0C;E1CmgO5C;E0CvmOF;IzCwJI,gByClDqC;E1CogOvC;E0C1mOF;IzCwJI,qByChD0C;E1CqgO5C;E0C7mOF;IzCwJI,gByC9CqC;E1CsgOvC;E0ChnOF;IzCwJI,gByC5CqC;E1CugOvC;E0CnnOF;IzCwJI,gByC1CqC;E1CwgOvC;E0CtnOF;IzCwJI,gByCxCqC;E1CygOvC;E0CznOF;IzCwJI,gByCtCqC;E1C0gOvC;E0C5nOF;IAqHQ,UAAU;IACV,SAAiC;E1C0gOvC;E0ChoOF;IzCwJI,eyChC8D;E1C2gOhE;E0CnoOF;IAqHQ,UAAU;IACV,eAAiC;E1CihOvC;E0CvoOF;IzCwJI,qByChC8D;E1CkhOhE;E0C1oOF;IAqHQ,UAAU;IACV,gBAAiC;E1CwhOvC;E0C9oOF;IzCwJI,sByChC8D;E1CyhOhE;E0CjpOF;IAqHQ,UAAU;IACV,UAAiC;E1C+hOvC;E0CrpOF;IzCwJI,gByChC8D;E1CgiOhE;E0CxpOF;IAqHQ,UAAU;IACV,gBAAiC;E1CsiOvC;E0C5pOF;IzCwJI,sByChC8D;E1CuiOhE;E0C/pOF;IAqHQ,UAAU;IACV,gBAAiC;E1C6iOvC;E0CnqOF;IzCwJI,sByChC8D;E1C8iOhE;E0CtqOF;IAqHQ,UAAU;IACV,UAAiC;E1CojOvC;E0C1qOF;IzCwJI,gByChC8D;E1CqjOhE;E0C7qOF;IAqHQ,UAAU;IACV,gBAAiC;E1C2jOvC;E0CjrOF;IzCwJI,sByChC8D;E1C4jOhE;E0CprOF;IAqHQ,UAAU;IACV,gBAAiC;E1CkkOvC;E0CxrOF;IzCwJI,sByChC8D;E1CmkOhE;E0C3rOF;IAqHQ,UAAU;IACV,UAAiC;E1CykOvC;E0C/rOF;IzCwJI,gByChC8D;E1C0kOhE;E0ClsOF;IAqHQ,UAAU;IACV,gBAAiC;E1CglOvC;E0CtsOF;IzCwJI,sByChC8D;E1CilOhE;E0CzsOF;IAqHQ,UAAU;IACV,gBAAiC;E1CulOvC;E0C7sOF;IzCwJI,sByChC8D;E1CwlOhE;E0ChtOF;IAqHQ,UAAU;IACV,WAAiC;E1C8lOvC;E0CptOF;IzCwJI,iByChC8D;E1C+lOhE;AACF;;AC3nOE;EyC7FF;IA4HM,UAAU;IACV,YAAY;E1CimOhB;E0C9tOF;IAgIM,UAAU;IACV,WAAW;E1CimOf;E0CluOF;IAoIM,UAAU;IACV,UAAU;E1CimOd;E0CtuOF;IAwIM,UAAU;IACV,eAAe;E1CimOnB;E0C1uOF;IA4IM,UAAU;IACV,UAAU;E1CimOd;E0C9uOF;IAgJM,UAAU;IACV,eAAe;E1CimOnB;E0ClvOF;IAoJM,UAAU;IACV,UAAU;E1CimOd;E0CtvOF;IAwJM,UAAU;IACV,UAAU;E1CimOd;E0C1vOF;IA4JM,UAAU;IACV,UAAU;E1CimOd;E0C9vOF;IAgKM,UAAU;IACV,UAAU;E1CimOd;E0ClwOF;IAoKM,UAAU;IACV,UAAU;E1CimOd;E0CtwOF;IzCwJI,gByCgBqC;E1CimOvC;E0CzwOF;IzCwJI,qByCmB0C;E1CimO5C;E0C5wOF;IzCwJI,gByCsBqC;E1CimOvC;E0C/wOF;IzCwJI,qByCyB0C;E1CimO5C;E0ClxOF;IzCwJI,gByC4BqC;E1CimOvC;E0CrxOF;IzCwJI,gByC+BqC;E1CimOvC;E0CxxOF;IzCwJI,gByCkCqC;E1CimOvC;E0C3xOF;IzCwJI,gByCqCqC;E1CimOvC;E0C9xOF;IzCwJI,gByCwCqC;E1CimOvC;E0CjyOF;IAoMQ,UAAU;IACV,SAAiC;E1CgmOvC;E0CryOF;IzCwJI,eyCgD8D;E1CgmOhE;E0CxyOF;IAoMQ,UAAU;IACV,eAAiC;E1CumOvC;E0C5yOF;IzCwJI,qByCgD8D;E1CumOhE;E0C/yOF;IAoMQ,UAAU;IACV,gBAAiC;E1C8mOvC;E0CnzOF;IzCwJI,sByCgD8D;E1C8mOhE;E0CtzOF;IAoMQ,UAAU;IACV,UAAiC;E1CqnOvC;E0C1zOF;IzCwJI,gByCgD8D;E1CqnOhE;E0C7zOF;IAoMQ,UAAU;IACV,gBAAiC;E1C4nOvC;E0Cj0OF;IzCwJI,sByCgD8D;E1C4nOhE;E0Cp0OF;IAoMQ,UAAU;IACV,gBAAiC;E1CmoOvC;E0Cx0OF;IzCwJI,sByCgD8D;E1CmoOhE;E0C30OF;IAoMQ,UAAU;IACV,UAAiC;E1C0oOvC;E0C/0OF;IzCwJI,gByCgD8D;E1C0oOhE;E0Cl1OF;IAoMQ,UAAU;IACV,gBAAiC;E1CipOvC;E0Ct1OF;IzCwJI,sByCgD8D;E1CipOhE;E0Cz1OF;IAoMQ,UAAU;IACV,gBAAiC;E1CwpOvC;E0C71OF;IzCwJI,sByCgD8D;E1CwpOhE;E0Ch2OF;IAoMQ,UAAU;IACV,UAAiC;E1C+pOvC;E0Cp2OF;IzCwJI,gByCgD8D;E1C+pOhE;E0Cv2OF;IAoMQ,UAAU;IACV,gBAAiC;E1CsqOvC;E0C32OF;IzCwJI,sByCgD8D;E1CsqOhE;E0C92OF;IAoMQ,UAAU;IACV,gBAAiC;E1C6qOvC;E0Cl3OF;IzCwJI,sByCgD8D;E1C6qOhE;E0Cr3OF;IAoMQ,UAAU;IACV,WAAiC;E1CorOvC;E0Cz3OF;IzCwJI,iByCgD8D;E1CorOhE;AACF;;ACxxOE;EyCrGF;IA2MM,UAAU;IACV,YAAY;E1CurOhB;E0Cn4OF;IA8MM,UAAU;IACV,WAAW;E1CwrOf;E0Cv4OF;IAiNM,UAAU;IACV,UAAU;E1CyrOd;E0C34OF;IAoNM,UAAU;IACV,eAAe;E1C0rOnB;E0C/4OF;IAuNM,UAAU;IACV,UAAU;E1C2rOd;E0Cn5OF;IA0NM,UAAU;IACV,eAAe;E1C4rOnB;E0Cv5OF;IA6NM,UAAU;IACV,UAAU;E1C6rOd;E0C35OF;IAgOM,UAAU;IACV,UAAU;E1C8rOd;E0C/5OF;IAmOM,UAAU;IACV,UAAU;E1C+rOd;E0Cn6OF;IAsOM,UAAU;IACV,UAAU;E1CgsOd;E0Cv6OF;IAyOM,UAAU;IACV,UAAU;E1CisOd;E0C36OF;IzCwJI,gByCoFqC;E1CksOvC;E0C96OF;IzCwJI,qByCsF0C;E1CmsO5C;E0Cj7OF;IzCwJI,gByCwFqC;E1CosOvC;E0Cp7OF;IzCwJI,qByC0F0C;E1CqsO5C;E0Cv7OF;IzCwJI,gByC4FqC;E1CssOvC;E0C17OF;IzCwJI,gByC8FqC;E1CusOvC;E0C77OF;IzCwJI,gByCgGqC;E1CwsOvC;E0Ch8OF;IzCwJI,gByCkGqC;E1CysOvC;E0Cn8OF;IzCwJI,gByCoGqC;E1C0sOvC;E0Ct8OF;IA+PQ,UAAU;IACV,SAAiC;E1C0sOvC;E0C18OF;IzCwJI,eyC0G8D;E1C2sOhE;E0C78OF;IA+PQ,UAAU;IACV,eAAiC;E1CitOvC;E0Cj9OF;IzCwJI,qByC0G8D;E1CktOhE;E0Cp9OF;IA+PQ,UAAU;IACV,gBAAiC;E1CwtOvC;E0Cx9OF;IzCwJI,sByC0G8D;E1CytOhE;E0C39OF;IA+PQ,UAAU;IACV,UAAiC;E1C+tOvC;E0C/9OF;IzCwJI,gByC0G8D;E1CguOhE;E0Cl+OF;IA+PQ,UAAU;IACV,gBAAiC;E1CsuOvC;E0Ct+OF;IzCwJI,sByC0G8D;E1CuuOhE;E0Cz+OF;IA+PQ,UAAU;IACV,gBAAiC;E1C6uOvC;E0C7+OF;IzCwJI,sByC0G8D;E1C8uOhE;E0Ch/OF;IA+PQ,UAAU;IACV,UAAiC;E1CovOvC;E0Cp/OF;IzCwJI,gByC0G8D;E1CqvOhE;E0Cv/OF;IA+PQ,UAAU;IACV,gBAAiC;E1C2vOvC;E0C3/OF;IzCwJI,sByC0G8D;E1C4vOhE;E0C9/OF;IA+PQ,UAAU;IACV,gBAAiC;E1CkwOvC;E0ClgPF;IzCwJI,sByC0G8D;E1CmwOhE;E0CrgPF;IA+PQ,UAAU;IACV,UAAiC;E1CywOvC;E0CzgPF;IzCwJI,gByC0G8D;E1C0wOhE;E0C5gPF;IA+PQ,UAAU;IACV,gBAAiC;E1CgxOvC;E0ChhPF;IzCwJI,sByC0G8D;E1CixOhE;E0CnhPF;IA+PQ,UAAU;IACV,gBAAiC;E1CuxOvC;E0CvhPF;IzCwJI,sByC0G8D;E1CwxOhE;E0C1hPF;IA+PQ,UAAU;IACV,WAAiC;E1C8xOvC;E0C9hPF;IzCwJI,iByC0G8D;E1C+xOhE;AACF;;ACz7OE;EyCzGF;IAqQM,UAAU;IACV,YAAY;E1CkyOhB;E0CxiPF;IAwQM,UAAU;IACV,WAAW;E1CmyOf;E0C5iPF;IA2QM,UAAU;IACV,UAAU;E1CoyOd;E0ChjPF;IA8QM,UAAU;IACV,eAAe;E1CqyOnB;E0CpjPF;IAiRM,UAAU;IACV,UAAU;E1CsyOd;E0CxjPF;IAoRM,UAAU;IACV,eAAe;E1CuyOnB;E0C5jPF;IAuRM,UAAU;IACV,UAAU;E1CwyOd;E0ChkPF;IA0RM,UAAU;IACV,UAAU;E1CyyOd;E0CpkPF;IA6RM,UAAU;IACV,UAAU;E1C0yOd;E0CxkPF;IAgSM,UAAU;IACV,UAAU;E1C2yOd;E0C5kPF;IAmSM,UAAU;IACV,UAAU;E1C4yOd;E0ChlPF;IzCwJI,gByC8IqC;E1C6yOvC;E0CnlPF;IzCwJI,qByCgJ0C;E1C8yO5C;E0CtlPF;IzCwJI,gByCkJqC;E1C+yOvC;E0CzlPF;IzCwJI,qByCoJ0C;E1CgzO5C;E0C5lPF;IzCwJI,gByCsJqC;E1CizOvC;E0C/lPF;IzCwJI,gByCwJqC;E1CkzOvC;E0ClmPF;IzCwJI,gByC0JqC;E1CmzOvC;E0CrmPF;IzCwJI,gByC4JqC;E1CozOvC;E0CxmPF;IzCwJI,gByC8JqC;E1CqzOvC;E0C3mPF;IAyTQ,UAAU;IACV,SAAiC;E1CqzOvC;E0C/mPF;IzCwJI,eyCoK8D;E1CszOhE;E0ClnPF;IAyTQ,UAAU;IACV,eAAiC;E1C4zOvC;E0CtnPF;IzCwJI,qByCoK8D;E1C6zOhE;E0CznPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cm0OvC;E0C7nPF;IzCwJI,sByCoK8D;E1Co0OhE;E0ChoPF;IAyTQ,UAAU;IACV,UAAiC;E1C00OvC;E0CpoPF;IzCwJI,gByCoK8D;E1C20OhE;E0CvoPF;IAyTQ,UAAU;IACV,gBAAiC;E1Ci1OvC;E0C3oPF;IzCwJI,sByCoK8D;E1Ck1OhE;E0C9oPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cw1OvC;E0ClpPF;IzCwJI,sByCoK8D;E1Cy1OhE;E0CrpPF;IAyTQ,UAAU;IACV,UAAiC;E1C+1OvC;E0CzpPF;IzCwJI,gByCoK8D;E1Cg2OhE;E0C5pPF;IAyTQ,UAAU;IACV,gBAAiC;E1Cs2OvC;E0ChqPF;IzCwJI,sByCoK8D;E1Cu2OhE;E0CnqPF;IAyTQ,UAAU;IACV,gBAAiC;E1C62OvC;E0CvqPF;IzCwJI,sByCoK8D;E1C82OhE;E0C1qPF;IAyTQ,UAAU;IACV,UAAiC;E1Co3OvC;E0C9qPF;IzCwJI,gByCoK8D;E1Cq3OhE;E0CjrPF;IAyTQ,UAAU;IACV,gBAAiC;E1C23OvC;E0CrrPF;IzCwJI,sByCoK8D;E1C43OhE;E0CxrPF;IAyTQ,UAAU;IACV,gBAAiC;E1Ck4OvC;E0C5rPF;IzCwJI,sByCoK8D;E1Cm4OhE;E0C/rPF;IAyTQ,UAAU;IACV,WAAiC;E1Cy4OvC;E0CnsPF;IzCwJI,iByCoK8D;E1C04OhE;AACF;;AC/kPI;EyCxHJ;IA+TM,UAAU;IACV,YAAY;E1C64OhB;E0C7sPF;IAkUM,UAAU;IACV,WAAW;E1C84Of;E0CjtPF;IAqUM,UAAU;IACV,UAAU;E1C+4Od;E0CrtPF;IAwUM,UAAU;IACV,eAAe;E1Cg5OnB;E0CztPF;IA2UM,UAAU;IACV,UAAU;E1Ci5Od;E0C7tPF;IA8UM,UAAU;IACV,eAAe;E1Ck5OnB;E0CjuPF;IAiVM,UAAU;IACV,UAAU;E1Cm5Od;E0CruPF;IAoVM,UAAU;IACV,UAAU;E1Co5Od;E0CzuPF;IAuVM,UAAU;IACV,UAAU;E1Cq5Od;E0C7uPF;IA0VM,UAAU;IACV,UAAU;E1Cs5Od;E0CjvPF;IA6VM,UAAU;IACV,UAAU;E1Cu5Od;E0CrvPF;IzCwJI,gByCwMqC;E1Cw5OvC;E0CxvPF;IzCwJI,qByC0M0C;E1Cy5O5C;E0C3vPF;IzCwJI,gByC4MqC;E1C05OvC;E0C9vPF;IzCwJI,qByC8M0C;E1C25O5C;E0CjwPF;IzCwJI,gByCgNqC;E1C45OvC;E0CpwPF;IzCwJI,gByCkNqC;E1C65OvC;E0CvwPF;IzCwJI,gByCoNqC;E1C85OvC;E0C1wPF;IzCwJI,gByCsNqC;E1C+5OvC;E0C7wPF;IzCwJI,gByCwNqC;E1Cg6OvC;E0ChxPF;IAmXQ,UAAU;IACV,SAAiC;E1Cg6OvC;E0CpxPF;IzCwJI,eyC8N8D;E1Ci6OhE;E0CvxPF;IAmXQ,UAAU;IACV,eAAiC;E1Cu6OvC;E0C3xPF;IzCwJI,qByC8N8D;E1Cw6OhE;E0C9xPF;IAmXQ,UAAU;IACV,gBAAiC;E1C86OvC;E0ClyPF;IzCwJI,sByC8N8D;E1C+6OhE;E0CryPF;IAmXQ,UAAU;IACV,UAAiC;E1Cq7OvC;E0CzyPF;IzCwJI,gByC8N8D;E1Cs7OhE;E0C5yPF;IAmXQ,UAAU;IACV,gBAAiC;E1C47OvC;E0ChzPF;IzCwJI,sByC8N8D;E1C67OhE;E0CnzPF;IAmXQ,UAAU;IACV,gBAAiC;E1Cm8OvC;E0CvzPF;IzCwJI,sByC8N8D;E1Co8OhE;E0C1zPF;IAmXQ,UAAU;IACV,UAAiC;E1C08OvC;E0C9zPF;IzCwJI,gByC8N8D;E1C28OhE;E0Cj0PF;IAmXQ,UAAU;IACV,gBAAiC;E1Ci9OvC;E0Cr0PF;IzCwJI,sByC8N8D;E1Ck9OhE;E0Cx0PF;IAmXQ,UAAU;IACV,gBAAiC;E1Cw9OvC;E0C50PF;IzCwJI,sByC8N8D;E1Cy9OhE;E0C/0PF;IAmXQ,UAAU;IACV,UAAiC;E1C+9OvC;E0Cn1PF;IzCwJI,gByC8N8D;E1Cg+OhE;E0Ct1PF;IAmXQ,UAAU;IACV,gBAAiC;E1Cs+OvC;E0C11PF;IzCwJI,sByC8N8D;E1Cu+OhE;E0C71PF;IAmXQ,UAAU;IACV,gBAAiC;E1C6+OvC;E0Cj2PF;IzCwJI,sByC8N8D;E1C8+OhE;E0Cp2PF;IAmXQ,UAAU;IACV,WAAiC;E1Co/OvC;E0Cx2PF;IzCwJI,iByC8N8D;E1Cq/OhE;AACF;;ACruPI;EyCvIJ;IAyXM,UAAU;IACV,YAAY;E1Cw/OhB;E0Cl3PF;IA4XM,UAAU;IACV,WAAW;E1Cy/Of;E0Ct3PF;IA+XM,UAAU;IACV,UAAU;E1C0/Od;E0C13PF;IAkYM,UAAU;IACV,eAAe;E1C2/OnB;E0C93PF;IAqYM,UAAU;IACV,UAAU;E1C4/Od;E0Cl4PF;IAwYM,UAAU;IACV,eAAe;E1C6/OnB;E0Ct4PF;IA2YM,UAAU;IACV,UAAU;E1C8/Od;E0C14PF;IA8YM,UAAU;IACV,UAAU;E1C+/Od;E0C94PF;IAiZM,UAAU;IACV,UAAU;E1CggPd;E0Cl5PF;IAoZM,UAAU;IACV,UAAU;E1CigPd;E0Ct5PF;IAuZM,UAAU;IACV,UAAU;E1CkgPd;E0C15PF;IzCwJI,gByCkQqC;E1CmgPvC;E0C75PF;IzCwJI,qByCoQ0C;E1CogP5C;E0Ch6PF;IzCwJI,gByCsQqC;E1CqgPvC;E0Cn6PF;IzCwJI,qByCwQ0C;E1CsgP5C;E0Ct6PF;IzCwJI,gByC0QqC;E1CugPvC;E0Cz6PF;IzCwJI,gByC4QqC;E1CwgPvC;E0C56PF;IzCwJI,gByC8QqC;E1CygPvC;E0C/6PF;IzCwJI,gByCgRqC;E1C0gPvC;E0Cl7PF;IzCwJI,gByCkRqC;E1C2gPvC;E0Cr7PF;IA6aQ,UAAU;IACV,SAAiC;E1C2gPvC;E0Cz7PF;IzCwJI,eyCwR8D;E1C4gPhE;E0C57PF;IA6aQ,UAAU;IACV,eAAiC;E1CkhPvC;E0Ch8PF;IzCwJI,qByCwR8D;E1CmhPhE;E0Cn8PF;IA6aQ,UAAU;IACV,gBAAiC;E1CyhPvC;E0Cv8PF;IzCwJI,sByCwR8D;E1C0hPhE;E0C18PF;IA6aQ,UAAU;IACV,UAAiC;E1CgiPvC;E0C98PF;IzCwJI,gByCwR8D;E1CiiPhE;E0Cj9PF;IA6aQ,UAAU;IACV,gBAAiC;E1CuiPvC;E0Cr9PF;IzCwJI,sByCwR8D;E1CwiPhE;E0Cx9PF;IA6aQ,UAAU;IACV,gBAAiC;E1C8iPvC;E0C59PF;IzCwJI,sByCwR8D;E1C+iPhE;E0C/9PF;IA6aQ,UAAU;IACV,UAAiC;E1CqjPvC;E0Cn+PF;IzCwJI,gByCwR8D;E1CsjPhE;E0Ct+PF;IA6aQ,UAAU;IACV,gBAAiC;E1C4jPvC;E0C1+PF;IzCwJI,sByCwR8D;E1C6jPhE;E0C7+PF;IA6aQ,UAAU;IACV,gBAAiC;E1CmkPvC;E0Cj/PF;IzCwJI,sByCwR8D;E1CokPhE;E0Cp/PF;IA6aQ,UAAU;IACV,UAAiC;E1C0kPvC;E0Cx/PF;IzCwJI,gByCwR8D;E1C2kPhE;E0C3/PF;IA6aQ,UAAU;IACV,gBAAiC;E1CilPvC;E0C//PF;IzCwJI,sByCwR8D;E1CklPhE;E0ClgQF;IA6aQ,UAAU;IACV,gBAAiC;E1CwlPvC;E0CtgQF;IzCwJI,sByCwR8D;E1CylPhE;E0CzgQF;IA6aQ,UAAU;IACV,WAAiC;E1C+lPvC;E0C7gQF;IzCwJI,iByCwR8D;E1CgmPhE;AACF;;A0C/lPA;EzC1RI,qByC1JgB;EzC0JhB,sByC1JgB;EAublB,oBAvbkB;A1CyhQpB;;A0CrmPA;EAKI,uBAzbgB;A1C6hQpB;;A0CzmPA;EAOI,qCAA4C;A1CsmPhD;;A0C7mPA;EAUI,uBAAuB;A1CumP3B;;A0CjnPA;EzC1RI,cyCsSiC;EzCtSjC,eyCuSiC;EACjC,aAAa;A1CymPjB;;A0CvnPA;EAgBM,SAAS;EACT,qBAAqB;A1C2mP3B;;A0C5nPA;EAmBM,qBAAqB;A1C6mP3B;;A0ChoPA;EAqBM,gBAAgB;A1C+mPtB;;A0CpoPA;EAuBI,aAAa;A1CinPjB;;A0CxoPA;EAyBI,eAAe;A1CmnPnB;;A0C5oPA;EA2BI,mBAAmB;A1CqnPvB;;ACr+PE;EyCqVF;IA+BM,aAAa;E1CsnPjB;AACF;;AC/9PE;EyCyUF;IAmCM,aAAa;E1CwnPjB;AACF;;A0CtnPE;EACE,oBAAY;EzCjUZ,wCyCkU2D;EzClU3D,yCyCmU2D;A1CynP/D;;A0C5nPE;EAKI,8BAA8B;EAC9B,+BAA+B;A1C2nPrC;;A0CjoPE;EASM,iBAAY;A1C4nPpB;;ACpgQE;EyC+XA;IAYQ,iBAAY;E1C8nPpB;AACF;;ACtgQE;EyC2XA;IAeQ,iBAAY;E1CioPpB;AACF;;ACxgQE;EyCuXA;IAkBQ,iBAAY;E1CooPpB;AACF;;AC1gQE;EyCmXA;IAqBQ,iBAAY;E1CuoPpB;AACF;;AC5gQE;EyC+WA;IAwBQ,iBAAY;E1C0oPpB;AACF;;AC7gQI;EyC0WF;IA2BQ,iBAAY;E1C6oPpB;AACF;;ACzgQI;EyCgWF;IA8BQ,iBAAY;E1CgpPpB;AACF;;AC1gQI;EyC2VF;IAiCQ,iBAAY;E1CmpPpB;AACF;;ACtgQI;EyCiVF;IAoCQ,iBAAY;E1CspPpB;AACF;;A0C3rPE;EASM,oBAAY;A1CsrPpB;;AC9jQE;EyC+XA;IAYQ,oBAAY;E1CwrPpB;AACF;;AChkQE;EyC2XA;IAeQ,oBAAY;E1C2rPpB;AACF;;AClkQE;EyCuXA;IAkBQ,oBAAY;E1C8rPpB;AACF;;ACpkQE;EyCmXA;IAqBQ,oBAAY;E1CisPpB;AACF;;ACtkQE;EyC+WA;IAwBQ,oBAAY;E1CosPpB;AACF;;ACvkQI;EyC0WF;IA2BQ,oBAAY;E1CusPpB;AACF;;ACnkQI;EyCgWF;IA8BQ,oBAAY;E1C0sPpB;AACF;;ACpkQI;EyC2VF;IAiCQ,oBAAY;E1C6sPpB;AACF;;AChkQI;EyCiVF;IAoCQ,oBAAY;E1CgtPpB;AACF;;A0CrvPE;EASM,mBAAY;A1CgvPpB;;ACxnQE;EyC+XA;IAYQ,mBAAY;E1CkvPpB;AACF;;AC1nQE;EyC2XA;IAeQ,mBAAY;E1CqvPpB;AACF;;AC5nQE;EyCuXA;IAkBQ,mBAAY;E1CwvPpB;AACF;;AC9nQE;EyCmXA;IAqBQ,mBAAY;E1C2vPpB;AACF;;AChoQE;EyC+WA;IAwBQ,mBAAY;E1C8vPpB;AACF;;ACjoQI;EyC0WF;IA2BQ,mBAAY;E1CiwPpB;AACF;;AC7nQI;EyCgWF;IA8BQ,mBAAY;E1CowPpB;AACF;;AC9nQI;EyC2VF;IAiCQ,mBAAY;E1CuwPpB;AACF;;AC1nQI;EyCiVF;IAoCQ,mBAAY;E1C0wPpB;AACF;;A0C/yPE;EASM,oBAAY;A1C0yPpB;;AClrQE;EyC+XA;IAYQ,oBAAY;E1C4yPpB;AACF;;ACprQE;EyC2XA;IAeQ,oBAAY;E1C+yPpB;AACF;;ACtrQE;EyCuXA;IAkBQ,oBAAY;E1CkzPpB;AACF;;ACxrQE;EyCmXA;IAqBQ,oBAAY;E1CqzPpB;AACF;;AC1rQE;EyC+WA;IAwBQ,oBAAY;E1CwzPpB;AACF;;AC3rQI;EyC0WF;IA2BQ,oBAAY;E1C2zPpB;AACF;;ACvrQI;EyCgWF;IA8BQ,oBAAY;E1C8zPpB;AACF;;ACxrQI;EyC2VF;IAiCQ,oBAAY;E1Ci0PpB;AACF;;ACprQI;EyCiVF;IAoCQ,oBAAY;E1Co0PpB;AACF;;A0Cz2PE;EASM,iBAAY;A1Co2PpB;;AC5uQE;EyC+XA;IAYQ,iBAAY;E1Cs2PpB;AACF;;AC9uQE;EyC2XA;IAeQ,iBAAY;E1Cy2PpB;AACF;;AChvQE;EyCuXA;IAkBQ,iBAAY;E1C42PpB;AACF;;AClvQE;EyCmXA;IAqBQ,iBAAY;E1C+2PpB;AACF;;ACpvQE;EyC+WA;IAwBQ,iBAAY;E1Ck3PpB;AACF;;ACrvQI;EyC0WF;IA2BQ,iBAAY;E1Cq3PpB;AACF;;ACjvQI;EyCgWF;IA8BQ,iBAAY;E1Cw3PpB;AACF;;AClvQI;EyC2VF;IAiCQ,iBAAY;E1C23PpB;AACF;;AC9uQI;EyCiVF;IAoCQ,iBAAY;E1C83PpB;AACF;;A0Cn6PE;EASM,oBAAY;A1C85PpB;;ACtyQE;EyC+XA;IAYQ,oBAAY;E1Cg6PpB;AACF;;ACxyQE;EyC2XA;IAeQ,oBAAY;E1Cm6PpB;AACF;;AC1yQE;EyCuXA;IAkBQ,oBAAY;E1Cs6PpB;AACF;;AC5yQE;EyCmXA;IAqBQ,oBAAY;E1Cy6PpB;AACF;;AC9yQE;EyC+WA;IAwBQ,oBAAY;E1C46PpB;AACF;;AC/yQI;EyC0WF;IA2BQ,oBAAY;E1C+6PpB;AACF;;AC3yQI;EyCgWF;IA8BQ,oBAAY;E1Ck7PpB;AACF;;AC5yQI;EyC2VF;IAiCQ,oBAAY;E1Cq7PpB;AACF;;ACxyQI;EyCiVF;IAoCQ,oBAAY;E1Cw7PpB;AACF;;A0C79PE;EASM,mBAAY;A1Cw9PpB;;ACh2QE;EyC+XA;IAYQ,mBAAY;E1C09PpB;AACF;;ACl2QE;EyC2XA;IAeQ,mBAAY;E1C69PpB;AACF;;ACp2QE;EyCuXA;IAkBQ,mBAAY;E1Cg+PpB;AACF;;ACt2QE;EyCmXA;IAqBQ,mBAAY;E1Cm+PpB;AACF;;ACx2QE;EyC+WA;IAwBQ,mBAAY;E1Cs+PpB;AACF;;ACz2QI;EyC0WF;IA2BQ,mBAAY;E1Cy+PpB;AACF;;ACr2QI;EyCgWF;IA8BQ,mBAAY;E1C4+PpB;AACF;;ACt2QI;EyC2VF;IAiCQ,mBAAY;E1C++PpB;AACF;;ACl2QI;EyCiVF;IAoCQ,mBAAY;E1Ck/PpB;AACF;;A0CvhQE;EASM,oBAAY;A1CkhQpB;;AC15QE;EyC+XA;IAYQ,oBAAY;E1CohQpB;AACF;;AC55QE;EyC2XA;IAeQ,oBAAY;E1CuhQpB;AACF;;AC95QE;EyCuXA;IAkBQ,oBAAY;E1C0hQpB;AACF;;ACh6QE;EyCmXA;IAqBQ,oBAAY;E1C6hQpB;AACF;;ACl6QE;EyC+WA;IAwBQ,oBAAY;E1CgiQpB;AACF;;ACn6QI;EyC0WF;IA2BQ,oBAAY;E1CmiQpB;AACF;;AC/5QI;EyCgWF;IA8BQ,oBAAY;E1CsiQpB;AACF;;ACh6QI;EyC2VF;IAiCQ,oBAAY;E1CyiQpB;AACF;;AC55QI;EyCiV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B;A7C+zRnC;;A6C9zRI;EAGI,yBAAgD;A7C+zRxD;;A6C9zRI;EACE,oCAAwC;A7Ci0R9C;;A6C71RE;EACE,yBAAwB;A7Cg2R5B;;A6C/1RE;EAGI,yBAA0C;A7Cg2RhD;;A6C/1RE;EACE,oCAAmC;A7Ck2RvC;;A6C71RI;EACE,yBAA8B;A7Cg2RpC;;A6C/1RI;EAGI,yBAAgD;A7Cg2RxD;;A6C/1RI;EACE,oCAAyC;A7Ck2R/C;;A6Ch2RI;EACE,yBAA6B;A7Cm2RnC;;A6Cl2RI;EAGI,yBAAgD;A7Cm2RxD;;A6Cl2RI;EACE,oCAAwC;A7Cq2R9C;;A6Cj4RE;EACE,yBAAwB;A7Co4R5B;;A6Cn4RE;EAGI,yBAA0C;A7Co4RhD;;A6Cn4RE;EACE,oCAAmC;A7Cs4RvC;;A6Cj4RI;EACE,yBAA8B;A7Co4RpC;;A6Cn4RI;EAGI,yBAAgD;A7Co4RxD;;A6Cn4RI;EACE,oCAAyC;A7Cs4R/C;;A6Cp4RI;EACE,yBAA6B;A7Cu4RnC;;A6Ct4RI;EAGI,yBAAgD;A7Cu4RxD;;A6Ct4RI;EACE,oCAAwC;A7Cy4R9C;;A6Cr6RE;EACE,yBAAwB;A7Cw6R5B;;A6Cv6RE;EAGI,yBAA0C;A7Cw6RhD;;A6Cv6RE;EACE,oCAAmC;A7C06RvC;;A6Cr6RI;EACE,yBAA8B;A7Cw6RpC;;A6Cv6RI;EAGI,yBAAgD;A7Cw6RxD;;A6Cv6RI;EACE,oCAAyC;A7C06R/C;;A6Cx6RI;EACE,yBAA6B;A7C26RnC;;A6C16RI;EAGI,yBAAgD;A7C26RxD;;A6C16RI;EACE,oCAAwC;A7C66R9C;;A6C16RE;EACE,yBAAwB;A7C66R5B;;A6C56RE;EACE,oCAAmC;A7C+6RvC;;A6Cl7RE;EACE,yBAAwB;A7Cq7R5B;;A6Cp7RE;EACE,oCAAmC;A7Cu7RvC;;A6C17RE;EACE,yBAAwB;A7C67R5B;;A6C57RE;EACE,oCAAmC;A7C+7RvC;;A6Cl8RE;EACE,yBAAwB;A7Cq8R5B;;A6Cp8RE;EACE,oCAAmC;A7Cu8RvC;;A6C18RE;EACE,yBAAwB;A7C68R5B;;A6C58RE;EACE,oCAAmC;A7C+8RvC;;A6Cl9RE;EACE,yBAAwB;A7Cq9R5B;;A6Cp9RE;EACE,oCAAmC;A7Cu9RvC;;A6C19RE;EACE,yBAAwB;A7C69R5B;;A6C59RE;EACE,oCAAmC;A7C+9RvC;;A6Cl+RE;EACE,4BAAwB;A7Cq+R5B;;A6Cp+RE;EACE,uCAAmC;A7Cu+RvC;;A6C1+RE;EACE,yBAAwB;A7C6+R5B;;A6C5+RE;EACE,oCAAmC;A7C++RvC;;A8CnhSE;EACE,8BAAiC;A9CshSrC;;A8CvhSE;EACE,sCAAiC;A9C0hSrC;;A8C3hSE;EACE,iCAAiC;A9C8hSrC;;A8C/hSE;EACE,yCAAiC;A9CkiSrC;;A8C9hSE;EACE,4BAA4B;A9CiiShC;;A8CliSE;EACE,0BAA4B;A9CqiShC;;A8CtiSE;EACE,kCAA4B;A9CyiShC;;A8CriSE;EACE,sCAAkC;A9CwiStC;;A8CziSE;EACE,oCAAkC;A9C4iStC;;A8C7iSE;EACE,kCAAkC;A9CgjStC;;A8CjjSE;EACE,yCAAkC;A9CojStC;;A8CrjSE;EACE,wCAAkC;A9CwjStC;;A8CzjSE;EACE,wCAAkC;A9C4jStC;;A8C7jSE;EACE,iCAAkC;A9CgkStC;;A8CjkSE;EACE,+BAAkC;A9CokStC;;A8CrkSE;EACE,gCAAkC;A9CwkStC;;A8CzkSE;EACE,iCAAkC;A9C4kStC;;A8CxkSE;EACE,oCAAgC;A9C2kSpC;;A8C5kSE;EACE,kCAAgC;A9C+kSpC;;A8ChlSE;EACE,gCAAgC;A9CmlSpC;;A8CplSE;EACE,uCAAgC;A9CulSpC;;A8CxlSE;EACE,sCAAgC;A9C2lSpC;;A8C5lSE;EACE,sCAAgC;A9C+lSpC;;A8ChmSE;EACE,iCAAgC;A9CmmSpC;;A8CpmSE;EACE,+BAAgC;A9CumSpC;;A8CxmSE;EACE,6BAAgC;A9C2mSpC;;A8C5mSE;EACE,kCAAgC;A9C+mSpC;;A8C3mSE;EACE,+BAA8B;A9C8mSlC;;A8C/mSE;EACE,kCAA8B;A9CknSlC;;A8CnnSE;EACE,gCAA8B;A9CsnSlC;;A8CvnSE;EACE,8BAA8B;A9C0nSlC;;A8C3nSE;EACE,gCAA8B;A9C8nSlC;;A8C/nSE;EACE,6BAA8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0vTjC;;AoD3vTI;EACE,0BAA2B;ApD8vTjC;;AoD/vTI;EACE,4BAA2B;ApDkwTjC;;AoDnwTI;EACE,6BAA2B;ApDswTjC;;AoDvwTI;EACE,0BAA2B;ApD0wTjC;;AoD3wTI;EACE,6BAA2B;ApD8wTjC;;ACvrTE;EmDxFE;IACE,0BAA2B;EpDmxT/B;EoDpxTE;IACE,4BAA2B;EpDsxT/B;EoDvxTE;IACE,0BAA2B;EpDyxT/B;EoD1xTE;IACE,4BAA2B;EpD4xT/B;EoD7xTE;IACE,6BAA2B;EpD+xT/B;EoDhyTE;IACE,0BAA2B;EpDkyT/B;EoDnyTE;IACE,6BAA2B;EpDqyT/B;AACF;;AC3sTE;EmD5FE;IACE,0BAA2B;EpD2yT/B;EoD5yTE;IACE,4BAA2B;EpD8yT/B;EoD/yTE;IACE,0BAA2B;EpDizT/B;EoDlzTE;IACE,4BAA2B;EpDozT/B;EoDrzTE;IACE,6BAA2B;EpDuzT/B;EoDxzTE;IACE,0BAA2B;EpD0zT/B;EoD3zTE;IACE,6BAA2B;EpD6zT/B;AACF;;AC3tTE;EmDpGE;IACE,0BAA2B;EpDm0T/B;EoDp0TE;IACE,4BAA2B;EpDs0T/B;EoDv0TE;IACE,0BAA2B;EpDy0T/B;EoD10TE;IACE,4BAA2B;EpD40T/B;EoD70TE;IACE,6BAA2B;EpD+0T/B;EoDh1TE;IACE,0BAA2B;EpDk1T/B;EoDn1TE;IACE,6BAA2B;EpDq1T/B;AACF;;AC/uTE;EmDxGE;IACE,0BAA2B;EpD21T/B;EoD51TE;IACE,4BAA2B;EpD81T/B;EoD/1TE;IACE,0BAA2B;EpDi2T/B;EoDl2TE;IACE,4BAA2B;EpDo2T/B;EoDr2TE;IACE,6BAA2B;EpDu2T/B;EoDx2TE;IACE,0BAA2B;EpD02T/B;EoD32TE;IACE,6BAA2B;EpD62T/B;AACF;;ACxvTI;EmDvHA;IACE,0BAA2B;EpDm3T/B;EoDp3TE;IACE,4BAA2B;EpDs3T/B;EoDv3TE;IACE,0BAA2B;EpDy3T/B;EoD13TE;IACE,4BAA2B;EpD43T/B;EoD73TE;IACE,6BAA2B;EpD+3T/B;EoDh4TE;IACE,0BAA2B;EpDk4T/B;EoDn4TE;IACE,6BAA2B;EpDq4T/B;AACF;;ACjwTI;EmDtIA;IACE,0BAA2B;EpD24T/B;EoD54TE;IACE,4BAA2B;EpD84T/B;EoD/4TE;IACE,0BAA2B;EpDi5T/B;EoDl5TE;IACE,4BAA2B;EpDo5T/B;EoDr5TE;IACE,6BAA2B;EpDu5T/B;EoDx5TE;IACE,0BAA2B;EpD05T/B;EoD35TE;IACE,6BAA2B;EpD65T/B;AACF;;AoDr4TE;EACE,6BAAqC;ApDw4TzC;;AoDz4TE;EACE,8BAAqC;ApD44TzC;;AoD74TE;EACE,2BAAqC;ApDg5TzC;;AoDj5TE;EACE,4BAAqC;ApDo5TzC;;ACv1TE;EmDzDE;IACE,6BAAqC;EpDo5TzC;AACF;;ACz1TE;EmD1DE;IACE,6BAAqC;EpDu5TzC;AACF;;AC31TE;EmD3DE;IACE,6BAAqC;EpD05TzC;AACF;;AC71TE;EmD5DE;IACE,6BAAqC;EpD65TzC;AACF;;AC/1TE;EmD7DE;IACE,6BAAqC;EpDg6TzC;AACF;;ACh2TI;EmD/DA;IACE,6BAAqC;EpDm6TzC;AACF;;AC51TI;EmDtEA;IACE,6BAAqC;EpDs6TzC;AACF;;AC71TI;EmDxEA;IACE,6BAAqC;EpDy6TzC;AACF;;ACz1TI;EmD/EA;IACE,6BAAqC;EpD46TzC;AACF;;AC74TE;EmDzDE;IACE,8BAAqC;EpD08TzC;AACF;;AC/4TE;EmD1DE;IACE,8BAAqC;EpD68TzC;AACF;;ACj5TE;EmD3DE;IACE,8BAAqC;EpDg9TzC;AACF;;ACn5TE;EmD5DE;IACE,8BAAqC;EpDm9TzC;AACF;;ACr5TE;EmD7DE;IACE,8BAAqC;EpDs9TzC;AACF;;ACt5TI;EmD/DA;IACE,8BAAqC;EpDy9TzC;AACF;;ACl5TI;EmDtEA;IACE,8BAAqC;EpD49TzC;AACF;;ACn5TI;EmDxEA;IACE,8BAAqC;EpD+9TzC;AACF;;AC/4TI;EmD/EA;IACE,8BAAqC;EpDk+TzC;AACF;;ACn8TE;EmDzDE;IACE,2BAAqC;EpDggUzC;AACF;;ACr8TE;EmD1DE;IACE,2BAAqC;EpDmgUzC;AACF;;ACv8TE;EmD3DE;IACE,2BAAqC;EpDsgUzC;AACF;;ACz8TE;EmD5DE;IACE,2BAAqC;EpDygUzC;AACF;;AC38TE;EmD7DE;IACE,2BAAqC;EpD4gUzC;AACF;;AC58TI;EmD/DA;IACE,2BAAqC;EpD+gUzC;AACF;;ACx8TI;EmDtEA;IACE,2BAAqC;EpDkhUzC;AACF;;ACz8TI;EmDxEA;IACE,2BAAqC;EpDqhUzC;AACF;;ACr8TI;EmD/EA;IACE,2BAAqC;EpDwhUzC;AACF;;ACz/TE;EmDzDE;IACE,4BAAqC;EpDsjUzC;AACF;;AC3/TE;EmD1DE;IACE,4BAAqC;EpDyjUzC;AACF;;AC7/TE;EmD3DE;IACE,4BAAqC;EpD4jUzC;AACF;;AC//TE;EmD5DE;IACE,4BAAqC;EpD+jUzC;AACF;;ACjgUE;EmD7DE;IACE,4BAAqC;EpDkkUzC;AACF;;AClgUI;EmD/DA;IACE,4BAAqC;EpDqkUzC;AACF;;AC9/TI;EmDtEA;IACE,4BAAqC;EpDwkUzC;AACF;;AC//TI;EmDxEA;IACE,4BAAqC;EpD2kUzC;AACF;;AC3/TI;EmD/EA;IACE,4BAAqC;EpD8kUzC;AACF;;AoD7kUA;EACE,qCAAqC;ApDglUvC;;AoD9kUA;EACE,oCAAoC;ApDilUtC;;AoD/kUA;EACE,oCAAoC;ApDklUtC;;AoDhlUA;EACE,6BAA6B;ApDmlU/B;;AoDjlUA;EACE,qCAAqC;ApDolUvC;;AoDllUA;EACE,2BAAqC;ApDqlUvC;;AoDplUA;EACE,2BAAsC;ApDulUxC;;AoDtlUA;EACE,2BAAsC;ApDylUxC;;AoDxlUA;EACE,2BAAwC;ApD2lU1C;;AoD1lUA;EACE,2BAAoC;ApD6lUtC;;AoD3lUA;EACE,+LAAuC;ApD8lUzC;;AoD5lUA;EACE,+LAAyC;ApD+lU3C;;AoD7lUA;EACE,+LAA0C;ApDgmU5C;;AoD9lUA;EACE,iCAAyC;ApDimU3C;;AoD/lUA;EACE,iCAAoC;ApDkmUtC;;AqDnsUE;EACE,yBAA+B;ArDssUnC;;AC/mUE;EoDrFE;IACE,yBAA+B;ErDwsUnC;AACF;;ACjnUE;EoDtFE;IACE,yBAA+B;ErD2sUnC;AACF;;ACnnUE;EoDvFE;IACE,yBAA+B;ErD8sUnC;AACF;;ACrnUE;EoDxFE;IACE,yBAA+B;ErDitUnC;AACF;;ACvnUE;EoDzFE;IACE,yBAA+B;ErDotUnC;AACF;;ACxnUI;EoD3FA;IACE,yBAA+B;ErDutUnC;AACF;;ACpnUI;EoDlGA;IACE,yBAA+B;ErD0tUnC;AACF;;ACrnUI;EoDpGA;IACE,yBAA+B;ErD6tUnC;AACF;;ACjnUI;EoD3GA;IACE,yBAA+B;ErDguUnC;AACF;;AqD7vUE;EACE,wBAA+B;ArDgwUnC;;ACzqUE;EoDrFE;IACE,wBAA+B;ErDkwUnC;AACF;;AC3qUE;EoDtFE;IACE,wBAA+B;ErDqwUnC;AACF;;AC7qUE;EoDvFE;IACE,wBAA+B;ErDwwUnC;AACF;;AC/qUE;EoDxFE;IACE,wBAA+B;ErD2wUnC;AACF;;ACjrUE;EoDzFE;IACE,wBAA+B;ErD8wUnC;AACF;;AClrUI;EoD3FA;IACE,wBAA+B;ErDixUnC;AACF;;AC9qUI;EoDlGA;IACE,wBAA+B;ErDoxUnC;AACF;;AC/qUI;EoDpGA;IACE,wBAA+B;ErDuxUnC;AACF;;AC3qUI;EoD3GA;IACE,wBAA+B;ErD0xUnC;AACF;;AqDvzUE;EACE,0BAA+B;ArD0zUnC;;ACnuUE;EoDrFE;IACE,0BAA+B;ErD4zUnC;AACF;;ACruUE;EoDtFE;IACE,0BAA+B;ErD+zUnC;AACF;;ACvuUE;EoDvFE;IACE,0BAA+B;ErDk0UnC;AACF;;ACzuUE;EoDxFE;IACE,0BAA+B;ErDq0UnC;AACF;;AC3uUE;EoDzFE;IACE,0BAA+B;ErDw0UnC;AACF;;AC5uUI;EoD3FA;IACE,0BAA+B;ErD20UnC;AACF;;ACxuUI;EoDlGA;IACE,0BAA+B;ErD80UnC;AACF;;ACzuUI;EoDpGA;IACE,0BAA+B;ErDi1UnC;AACF;;ACruUI;EoD3GA;IACE,0BAA+B;ErDo1UnC;AACF;;AqDj3UE;EACE,gCAA+B;ArDo3UnC;;AC7xUE;EoDrFE;IACE,gCAA+B;ErDs3UnC;AACF;;AC/xUE;EoDtFE;IACE,gCAA+B;ErDy3UnC;AACF;;ACjyUE;EoDvFE;IACE,gCAA+B;ErD43UnC;AACF;;ACnyUE;EoDxFE;IACE,gCAA+B;ErD+3UnC;AACF;;ACryUE;EoDzFE;IACE,gCAA+B;ErDk4UnC;AACF;;ACtyUI;EoD3FA;IACE,gCAA+B;ErDq4UnC;AACF;;AClyUI;EoDlGA;IACE,gCAA+B;ErDw4UnC;AACF;;ACnyUI;EoDpGA;IACE,gCAA+B;ErD24UnC;AACF;;AC/xUI;EoD3GA;IACE,gCAA+B;ErD84UnC;AACF;;AqD36UE;EACE,+BAA+B;ArD86UnC;;ACv1UE;EoDrFE;IACE,+BAA+B;ErDg7UnC;AACF;;ACz1UE;EoDtFE;IACE,+BAA+B;ErDm7UnC;AACF;;AC31UE;EoDvFE;IACE,+BAA+B;ErDs7UnC;AACF;;AC71UE;EoDxFE;IACE,+BAA+B;ErDy7UnC;AACF;;AC/1UE;EoDzFE;IACE,+BAA+B;ErD47UnC;AACF;;ACh2UI;EoD3FA;IACE,+BAA+B;ErD+7UnC;AACF;;AC51UI;EoDlGA;IACE,+BAA+B;ErDk8UnC;AACF;;AC71UI;EoDpGA;IACE,+BAA+B;ErDq8UnC;AACF;;ACz1UI;EoD3GA;IACE,+BAA+B;ErDw8UnC;AACF;;AqDv8UA;EACE,wBAAwB;ArD08U1B;;AqDx8UA;EACE,uBAAuB;EACvB,iCAAiC;EACjC,yBAAyB;EACzB,2BAA2B;EAC3B,qBAAqB;EACrB,6BAA6B;EAC7B,8BAA8B;EAC9B,wBAAwB;ArD28U1B;;AC55UE;EoD5CA;IACE,wBAAwB;ErD48U1B;AACF;;AC95UE;EoD5CA;IACE,wBAAwB;ErD88U1B;AACF;;ACh6UE;EoD5CA;IACE,wBAAwB;ErDg9U1B;AACF;;ACl6UE;EoD5CA;IACE,wBAAwB;ErDk9U1B;AACF;;ACp6UE;EoD5CA;IACE,wBAAwB;ErDo9U1B;AACF;;ACr6UI;EoD7CF;IACE,wBAAwB;ErDs9U1B;AACF;;ACj6UI;EoDnDF;IACE,wBAAwB;ErDw9U1B;AACF;;ACl6UI;EoDpDF;IACE,wBAAwB;ErD09U1B;AACF;;AC95UI;EoD1DF;IACE,wBAAwB;ErD49U1B;AACF;;AqD39UA;EACE,6BAA6B;ArD89U/B;;ACt9UE;EoDLA;IACE,6BAA6B;ErD+9U/B;AACF;;ACx9UE;EoDLA;IACE,6BAA6B;ErDi+U/B;AACF;;AC19UE;EoDLA;IACE,6BAA6B;ErDm+U/B;AACF;;AC59UE;EoDLA;IACE,6BAA6B;ErDq+U/B;AACF;;AC99UE;EoDLA;IACE,6BAA6B;ErDu+U/B;AACF;;AC/9UI;EoDNF;IACE,6BAA6B;ErDy+U/B;AACF;;AC39UI;EoDZF;IACE,6BAA6B;ErD2+U/B;AACF;;AC59UI;EoDbF;IACE,6BAA6B;ErD6+U/B;AACF;;ACx9UI;EoDnBF;IACE,6BAA6B;ErD++U/B;AACF;;AsDzmVA,iBAAA;ACWA;EACE,oBAAoB;EACpB,aAAa;EACb,sBAAsB;EACtB,8BAA8B;AvDkmVhC;;AuDtmVA;EAMI,gBAAgB;AvDomVpB;;AuD1mVA;EASM,mBAAmB;AvDqmVzB;;AuD9mVA;EAeM,uBxDXyB;EwDYzB,cxDzBuB;AC4nV7B;;AuDnnVA;;EAmBQ,cAAc;AvDqmVtB;;AuDxnVA;EAqBQ,cxD9BqB;ACqoV7B;;AuD5nVA;EAuBQ,4BxDhCqB;ACyoV7B;;AuDhoVA;;EA0BU,cxDnCmB;AC8oV7B;;ACviVE;EsD9FF;IA6BU,uBxDzBqB;ECsoV7B;AACF;;AuD3oVA;;EAgCQ,4BxDzCqB;ACypV7B;;AuDhpVA;;;EAqCU,yB7C6DuB;E6C5DvB,cxD/CmB;ACgqV7B;;AuDvpVA;EAyCU,cxDlDmB;EwDmDnB,YAAY;AvDknVtB;;AuD5pVA;EA4CY,UAAU;AvDonVtB;;AuDhqVA;EA+CY,uBAAwB;EACxB,UAAU;AvDqnVtB;;AuDrqVA;EAoDY,cxD7DiB;ACkrV7B;;AuDzqVA;EAsDc,uCxD/De;ACsrV7B;;AuD7qVA;EA0Dc,yBxDnEe;EwDoEf,qBxDpEe;EwDqEf,YxDxDiB;AC+qV/B;;AuDnrVA;EAkEU,4EAAyG;AvDqnVnH;;ACrmVE;EsDlFF;IAqEc,4EAAyG;EvDunVrH;AACF;;AuD7rVA;EAeM,yBxDxBuB;EwDyBvB,YxDZyB;AC8rV/B;;AuDlsVA;;EAmBQ,cAAc;AvDorVtB;;AuDvsVA;EAqBQ,YxDjBuB;ACusV/B;;AuD3sVA;EAuBQ,+BxDnBuB;AC2sV/B;;AuD/sVA;;EA0BU,YxDtBqB;ACgtV/B;;ACtnVE;EsD9FF;IA6BU,yBxDtCmB;ECkuV3B;AACF;;AuD1tVA;;EAgCQ,+BxD5BuB;AC2tV/B;;AuD/tVA;;;EAqCU,uB7C6DuB;E6C5DvB,YxDlCqB;ACkuV/B;;AuDtuVA;EAyCU,YxDrCqB;EwDsCrB,YAAY;AvDisVtB;;AuD3uVA;EA4CY,UAAU;AvDmsVtB;;AuD/uVA;EA+CY,yBAAwB;EACxB,UAAU;AvDosVtB;;AuDpvVA;EAoDY,YxDhDmB;ACovV/B;;AuDxvVA;EAsDc,uCxD/De;ACqwV7B;;AuD5vVA;EA0Dc,uBxDtDiB;EwDuDjB,mBxDvDiB;EwDwDjB,cxDrEe;AC2wV7B;;AuDlwVA;EAkEU,8EAAyG;AvDosVnH;;ACprVE;EsDlFF;IAqEc,8EAAyG;EvDssVrH;AACF;;AuD5wVA;EAeM,4BxDbwB;EwDcxB,yB7CqDe;AV4sVrB;;AuDjxVA;;EAmBQ,cAAc;AvDmwVtB;;AuDtxVA;EAqBQ,yB7CgDa;AVqtVrB;;AuD1xVA;EAuBQ,yB7C8Ca;AVytVrB;;AuD9xVA;;EA0BU,yB7C2CW;AV8tVrB;;ACrsVE;EsD9FF;IA6BU,4BxD3BoB;ECsyV5B;AACF;;AuDzyVA;;EAgCQ,yB7CqCa;AVyuVrB;;AuD9yVA;;;EAqCU,yB7C6DuB;E6C5DvB,yB7C+BW;AVgvVrB;;AuDrzVA;EAyCU,yB7C4BW;E6C3BX,YAAY;AvDgxVtB;;AuD1zVA;EA4CY,UAAU;AvDkxVtB;;AuD9zVA;EA+CY,4BAAwB;EACxB,UAAU;AvDmxVtB;;AuDn0VA;EAoDY,yB7CiBS;AVkwVrB;;AuDv0VA;EAsDc,uCxD/De;ACo1V7B;;AuD30VA;EA0Dc,oC7CWO;E6CVP,gC7CUO;E6CTP,iBxD1DgB;AC+0V9B;;AuDj1VA;EAkEU,iFAAyG;AvDmxVnH;;ACnwVE;EsDlFF;IAqEc,iFAAyG;EvDqxVrH;AACF;;AuD31VA;EAeM,yBxDpBwB;EwDqBxB,W7CuDU;AVyxVhB;;AuDh2VA;;EAmBQ,cAAc;AvDk1VtB;;AuDr2VA;EAqBQ,W7CkDQ;AVkyVhB;;AuDz2VA;EAuBQ,+B7CgDQ;AVsyVhB;;AuD72VA;;EA0BU,W7C6CM;AV2yVhB;;ACpxVE;EsD9FF;IA6BU,yBxDlCoB;EC43V5B;AACF;;AuDx3VA;;EAgCQ,+B7CuCQ;AVszVhB;;AuD73VA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV6zVhB;;AuDp4VA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD+1VtB;;AuDz4VA;EA4CY,UAAU;AvDi2VtB;;AuD74VA;EA+CY,yBAAwB;EACxB,UAAU;AvDk2VtB;;AuDl5VA;EAoDY,W7CmBI;AV+0VhB;;AuDt5VA;EAsDc,uCxD/De;ACm6V7B;;AuD15VA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDjEgB;ACq6V9B;;AuDh6VA;EAkEU,gFAAyG;AvDk2VnH;;ACl1VE;EsDlFF;IAqEc,gFAAyG;EvDo2VrH;AACF;;AuD16VA;EAeM,yBxDN4B;EwDO5B,W7CuDU;AVw2VhB;;AuD/6VA;;EAmBQ,cAAc;AvDi6VtB;;AuDp7VA;EAqBQ,W7CkDQ;AVi3VhB;;AuDx7VA;EAuBQ,+B7CgDQ;AVq3VhB;;AuD57VA;;EA0BU,W7C6CM;AV03VhB;;ACn2VE;EsD9FF;IA6BU,yBxDpBwB;EC67VhC;AACF;;AuDv8VA;;EAgCQ,+B7CuCQ;AVq4VhB;;AuD58VA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV44VhB;;AuDn9VA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD86VtB;;AuDx9VA;EA4CY,UAAU;AvDg7VtB;;AuD59VA;EA+CY,yBAAwB;EACxB,UAAU;AvDi7VtB;;AuDj+VA;EAoDY,W7CmBI;AV85VhB;;AuDr+VA;EAsDc,uCxD/De;ACk/V7B;;AuDz+VA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDnDoB;ACs+VlC;;AuD/+VA;EAkEU,gFAAyG;AvDi7VnH;;ACj6VE;EsDlFF;IAqEc,gFAAyG;EvDm7VrH;AACF;;AuDz/VA;EAeM,yBxDJ4B;EwDK5B,W7CuDU;AVu7VhB;;AuD9/VA;;EAmBQ,cAAc;AvDg/VtB;;AuDngWA;EAqBQ,W7CkDQ;AVg8VhB;;AuDvgWA;EAuBQ,+B7CgDQ;AVo8VhB;;AuD3gWA;;EA0BU,W7C6CM;AVy8VhB;;ACl7VE;EsD9FF;IA6BU,yBxDlBwB;EC0gWhC;AACF;;AuDthWA;;EAgCQ,+B7CuCQ;AVo9VhB;;AuD3hWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV29VhB;;AuDliWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD6/VtB;;AuDviWA;EA4CY,UAAU;AvD+/VtB;;AuD3iWA;EA+CY,yBAAwB;EACxB,UAAU;AvDggWtB;;AuDhjWA;EAoDY,W7CmBI;AV6+VhB;;AuDpjWA;EAsDc,uCxD/De;ACikW7B;;AuDxjWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDjDoB;ACmjWlC;;AuD9jWA;EAkEU,gFAAyG;AvDggWnH;;ACh/VE;EsDlFF;IAqEc,gFAAyG;EvDkgWrH;AACF;;AuDxkWA;EAeM,yBxDL4B;EwDM5B,W7CuDU;AVsgWhB;;AuD7kWA;;EAmBQ,cAAc;AvD+jWtB;;AuDllWA;EAqBQ,W7CkDQ;AV+gWhB;;AuDtlWA;EAuBQ,+B7CgDQ;AVmhWhB;;AuD1lWA;;EA0BU,W7C6CM;AVwhWhB;;ACjgWE;EsD9FF;IA6BU,yBxDnBwB;EC0lWhC;AACF;;AuDrmWA;;EAgCQ,+B7CuCQ;AVmiWhB;;AuD1mWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AV0iWhB;;AuDjnWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD4kWtB;;AuDtnWA;EA4CY,UAAU;AvD8kWtB;;AuD1nWA;EA+CY,yBAAwB;EACxB,UAAU;AvD+kWtB;;AuD/nWA;EAoDY,W7CmBI;AV4jWhB;;AuDnoWA;EAsDc,uCxD/De;ACgpW7B;;AuDvoWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDlDoB;ACmoWlC;;AuD7oWA;EAkEU,gFAAyG;AvD+kWnH;;AC/jWE;EsDlFF;IAqEc,gFAAyG;EvDilWrH;AACF;;AuDvpWA;EAeM,yBxDP4B;EwDQ5B,W7CuDU;AVqlWhB;;AuD5pWA;;EAmBQ,cAAc;AvD8oWtB;;AuDjqWA;EAqBQ,W7CkDQ;AV8lWhB;;AuDrqWA;EAuBQ,+B7CgDQ;AVkmWhB;;AuDzqWA;;EA0BU,W7C6CM;AVumWhB;;AChlWE;EsD9FF;IA6BU,yBxDrBwB;EC2qWhC;AACF;;AuDprWA;;EAgCQ,+B7CuCQ;AVknWhB;;AuDzrWA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AVynWhB;;AuDhsWA;EAyCU,W7C8BM;E6C7BN,YAAY;AvD2pWtB;;AuDrsWA;EA4CY,UAAU;AvD6pWtB;;AuDzsWA;EA+CY,yBAAwB;EACxB,UAAU;AvD8pWtB;;AuD9sWA;EAoDY,W7CmBI;AV2oWhB;;AuDltWA;EAsDc,uCxD/De;AC+tW7B;;AuDttWA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxDpDoB;ACotWlC;;AuD5tWA;EAkEU,gFAAyG;AvD8pWnH;;AC9oWE;EsDlFF;IAqEc,gFAAyG;EvDgqWrH;AACF;;AuDtuWA;EAeM,yBxDR4B;EwDS5B,yB7CqDe;AVsqWrB;;AuD3uWA;;EAmBQ,cAAc;AvD6tWtB;;AuDhvWA;EAqBQ,yB7CgDa;AV+qWrB;;AuDpvWA;EAuBQ,yB7C8Ca;AVmrWrB;;AuDxvWA;;EA0BU,yB7C2CW;AVwrWrB;;AC/pWE;EsD9FF;IA6BU,yBxDtBwB;EC2vWhC;AACF;;AuDnwWA;;EAgCQ,yB7CqCa;AVmsWrB;;AuDxwWA;;;EAqCU,yB7C6DuB;E6C5DvB,yB7C+BW;AV0sWrB;;AuD/wWA;EAyCU,yB7C4BW;E6C3BX,YAAY;AvD0uWtB;;AuDpxWA;EA4CY,UAAU;AvD4uWtB;;AuDxxWA;EA+CY,yBAAwB;EACxB,UAAU;AvD6uWtB;;AuD7xWA;EAoDY,yB7CiBS;AV4tWrB;;AuDjyWA;EAsDc,uCxD/De;AC8yW7B;;AuDryWA;EA0Dc,oC7CWO;E6CVP,gC7CUO;E6CTP,cxDrDoB;ACoyWlC;;AuD3yWA;EAkEU,gFAAyG;AvD6uWnH;;AC7tWE;EsDlFF;IAqEc,gFAAyG;EvD+uWrH;AACF;;AuDrzWA;EAeM,yBxDF2B;EwDG3B,W7CuDU;AVmvWhB;;AuD1zWA;;EAmBQ,cAAc;AvD4yWtB;;AuD/zWA;EAqBQ,W7CkDQ;AV4vWhB;;AuDn0WA;EAuBQ,+B7CgDQ;AVgwWhB;;AuDv0WA;;EA0BU,W7C6CM;AVqwWhB;;AC9uWE;EsD9FF;IA6BU,yBxDhBuB;ECo0W/B;AACF;;AuDl1WA;;EAgCQ,+B7CuCQ;AVgxWhB;;AuDv1WA;;;EAqCU,yB7C6DuB;E6C5DvB,W7CiCM;AVuxWhB;;AuD91WA;EAyCU,W7C8BM;E6C7BN,YAAY;AvDyzWtB;;AuDn2WA;EA4CY,UAAU;AvD2zWtB;;AuDv2WA;EA+CY,yBAAwB;EACxB,UAAU;AvD4zWtB;;AuD52WA;EAoDY,W7CmBI;AVyyWhB;;AuDh3WA;EAsDc,uCxD/De;AC63W7B;;AuDp3WA;EA0Dc,sB7CaE;E6CZF,kB7CYE;E6CXF,cxD/CmB;AC62WjC;;AuD13WA;EAkEU,gFAAyG;AvD4zWnH;;AC5yWE;EsDlFF;IAqEc,gFAAyG;EvD8zWrH;AACF;;AuDp4WA;EAyEM,eAhF0B;AvD+4WhC;;AClzWE;EsDtFF;IA6EQ,oBAnF8B;EvDm5WpC;AACF;;ACxzWE;EsDtFF;IAiFQ,mBAtF4B;EvDw5WlC;AACF;;AuDp5WA;EAsFM,mBAAmB;EACnB,aAAa;AvDk0WnB;;AuDz5WA;EAyFQ,YAAY;EACZ,cAAc;AvDo0WtB;;AuD95WA;EA4FI,gBAAgB;AvDs0WpB;;AuDl6WA;EA8FI,iBAAiB;AvDw0WrB;;AuDp0WA;EAEE,gBAAgB;AvDs0WlB;;AuDx0WA;EAII,SAAS;EACT,gBAAgB;EAChB,eAAe;EACf,kBAAkB;EAClB,QAAQ;EACR,qCAAqC;AvDw0WzC;;AuDj1WA;EAYI,YAAY;AvDy0WhB;;ACr2WE;EsDgBF;IAeI,aAAa;EvD20Wf;AACF;;AuD10WA;EACE,kBAAkB;AvD60WpB;;AC/2WE;EsDiCF;IAKM,aAAa;EvD80WjB;EuDn1WF;IAOQ,sBAAsB;EvD+0W5B;AACF;;ACp3WE;EsD6BF;IASI,aAAa;IACb,uBAAuB;EvDm1WzB;EuD71WF;ItD8BI,oBsDlBwC;EvDo1W1C;AACF;;AuDj1WA;;EAEE,YAAY;EACZ,cAAc;AvDo1WhB;;AuDl1WA;EACE,YAAY;EACZ,cAAc;EACd,oBApJ6B;AvDy+W/B;;AC14WE;EsDkDF;IAKI,kBArJgC;EvD6+WlC;AACF;;AwD1+WA;EACE,oBAN2B;AxDm/W7B;;ACx4WE;EuDtGF;IAII,kBAR+B;ExDu/WjC;EwDn/WF;IAOM,oBAV8B;ExDy/WlC;EwDt/WF;IASM,mBAX4B;ExD2/WhC;AACF;;AyD3/WA;EACE,yB1DO4B;E0DN5B,yBAJ+B;AzDkgXjC","file":"bulma.css"} \ No newline at end of file From 68d79f60901f90fe31c6d53fdcbc3b73c8d92805 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 29 Mar 2022 22:53:17 +0200 Subject: [PATCH 13/80] Modifica el renderizado de componentes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La función default_render() se implementa usando llamadas a funciones, nunca usando campos internos de la estructura. Esto es así para dar las mismas opciones a los temas que alteren el render de un componente dado. --- pagetop-user/src/lib.rs | 2 +- pagetop/src/base/component/block.rs | 22 ++-- pagetop/src/base/component/chunck.rs | 6 +- pagetop/src/base/component/container.rs | 42 +++++--- pagetop/src/base/component/form/button.rs | 49 +++++---- pagetop/src/base/component/form/date.rs | 100 +++++++++---------- pagetop/src/base/component/form/form.rs | 47 +++++---- pagetop/src/base/component/form/hidden.rs | 30 +++--- pagetop/src/base/component/form/input.rs | 116 +++++++++++----------- pagetop/src/base/component/form/mod.rs | 4 +- pagetop/src/base/component/grid/column.rs | 18 +++- pagetop/src/base/component/grid/row.rs | 18 +++- pagetop/src/base/component/image.rs | 19 ++-- pagetop/src/base/component/menu.rs | 53 +++++----- pagetop/src/base/component/mod.rs | 4 +- pagetop/src/base/module/demopage/mod.rs | 2 +- pagetop/src/html/optattr.rs | 11 -- pagetop/src/html/optiden.rs | 11 -- pagetop/src/lib.rs | 9 +- pagetop/src/prelude.rs | 1 + pagetop/src/response/page/assets.rs | 27 ++--- pagetop/src/response/page/page.rs | 18 ++-- pagetop/src/theme/definition.rs | 21 ++-- 23 files changed, 335 insertions(+), 295 deletions(-) diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 7ef2ecf3..dd0b362b 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -40,7 +40,7 @@ fn form_login() -> impl PageComponent { .with_help_text(t("username_help", &args![ "app" => SETTINGS.app.name.to_owned() ]).as_str()) - .autofocus(true) + .with_autofocus(true) ) .add(form::Input::password() .with_name("pass") diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 5e5a7159..976c27bc 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -31,15 +31,15 @@ impl PageComponent for Block { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let id = assets.serial_id(self.name(), self.id.value()); - let title = self.title.value(); + let id = assets.serial_id(self.name(), self.id()); html! { div id=(id) class="block" { - @if !title.is_empty() { - h2 class="block-title" { (title) } + @match self.title() { + Some(title) => h2 class="block-title" { (title) }, + None => {} } div class="block-body" { - @for html in self.html.iter() { + @for html in self.html().iter() { (*html) } } @@ -88,12 +88,16 @@ impl Block { // Block GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } - pub fn title(&self) -> &str { - self.title.value() + pub fn title(&self) -> &Option { + self.title.option() + } + + pub fn html(&self) -> &Vec { + &self.html } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index b03ac0c8..532584fc 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -28,7 +28,7 @@ impl PageComponent for Chunck { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - @for html in self.html.iter() { + @for html in self.html().iter() { (*html) } } @@ -65,6 +65,10 @@ impl Chunck { // Chunck GETTERS. + pub fn html(&self) -> &Vec { + &self.html + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index e76b48b4..cba905d6 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -1,12 +1,12 @@ use crate::prelude::*; -enum ContainerType { Header, Footer, Main, Section, Wrapper } +pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable: fn() -> bool, weight : i8, - id : OptIden, container : ContainerType, + id : OptIden, components: PageContainer, template : String, } @@ -17,8 +17,8 @@ impl PageComponent for Container { Container { renderable: always, weight : 0, - id : OptIden::none(), container : ContainerType::Wrapper, + id : OptIden::none(), components: PageContainer::new(), template : "default".to_owned(), } @@ -33,38 +33,38 @@ impl PageComponent for Container { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - match self.container { + match self.container_type() { ContainerType::Header => html! { - header id=[&self.id.option()] class="header" { + header id=[self.id()] class="header" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Footer => html! { - footer id=[&self.id.option()] class="footer" { + footer id=[self.id()] class="footer" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Main => html! { - main id=[&self.id.option()] class="main" { + main id=[self.id()] class="main" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, ContainerType::Section => html! { - section id=[&self.id.option()] class="section" { + section id=[self.id()] class="section" { div class="container" { - (self.components.render(assets)) + (self.render_components(assets)) } } }, _ => html! { - div id=[&self.id.option()] class="container" { - (self.components.render(assets)) + div id=[self.id()] class="container" { + (self.render_components(assets)) } } } @@ -126,13 +126,23 @@ impl Container { // Container GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn container_type(&self) -> &ContainerType { + &self.container + } + + pub fn id(&self) -> &Option { + self.id.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Container EXTRAS. + + pub fn render_components(&self, assets: &mut PageAssets) -> Markup { + html! { (self.components.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index fa9794f2..fbe25738 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -enum ButtonType {Button, Reset, Submit} +pub enum ButtonType {Button, Reset, Submit} pub struct Button { renderable : fn() -> bool, @@ -37,26 +37,29 @@ impl PageComponent for Button { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (button_type, button_class) = match &self.button_type { + let (button_type, button_class) = match self.button_type() { ButtonType::Button => ("button", "btn btn-primary form-button"), ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), - ButtonType::Submit => ("submit", "btn btn-primary form-submit") + ButtonType::Submit => ("submit", "btn btn-primary form-submit"), }; - let id = match &self.name.option() { - Some(name) => Some(format!("edit-{}", name)), + let id = match self.name() { + Some(name) => Some(concat_string!("edit-", name)), _ => None }; html! { button type=(button_type) - id=[&id] + id=[id] class=(button_class) - name=[&self.name.option()] - value=[&self.value.option()] - autofocus=[&self.autofocus.option()] - disabled=[&self.disabled.option()] + name=[self.name()] + value=[self.value()] + autofocus=[self.autofocus()] + disabled=[self.disabled()] { - (self.value.value()) + @match self.value() { + Some(value) => { (value) }, + None => {}, + } } } } @@ -102,7 +105,7 @@ impl Button { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -110,7 +113,7 @@ impl Button { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -125,20 +128,24 @@ impl Button { // Button GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn button_type(&self) -> &ButtonType { + &self.button_type } - pub fn value(&self) -> &str { - self.value.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn value(&self) -> &Option { + self.value.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() + } + + pub fn disabled(&self) -> &Option { + self.disabled.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 5e42bc6b..906f5bbc 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -45,10 +45,10 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (class, id) = match self.name.option() { + let (class, id) = match self.name() { Some(name) => ( - format!("form-item form-item-{} form-type-date", name), - Some(format!("edit-{}", name)) + concat_string!("form-item form-item-", name, " form-type-date"), + Some(concat_string!("edit-", name)) ), None => ( "form-item form-type-date".to_owned(), @@ -57,35 +57,33 @@ impl PageComponent for Date { }; html! { div class=(class) { - @if self.label.has_value() { - label class="form-label" for=[&id] { - (self.label.value()) " " - @if self.required.has_value() { - span + @match self.label() { + Some(label) => label class="form-label" for=[&id] { + (label) " " + @match self.required() { + Some(_) => span class="form-required" - title="Este campo es obligatorio." - { - "*" - } " " + title="Este campo es obligatorio." { "*" } " ", + None => {} } - } + }, + None => {} } input type="date" - id=[&id] + id=[id] class="form-control" - name=[&self.name.option()] - value=[&self.value.option()] - placeholder=[&self.placeholder.option()] - autofocus=[&self.autofocus.option()] - autocomplete=[&self.autocomplete.option()] - readonly=[&self.readonly.option()] - required=[&self.required.option()] - disabled=[&self.disabled.option()]; - @if self.help_text.has_value() { - div class="form-text" { - (self.help_text.value()) - } + name=[self.name()] + value=[self.value()] + placeholder=[self.placeholder()] + autofocus=[self.autofocus()] + autocomplete=[self.autocomplete()] + readonly=[self.readonly()] + required=[self.required()] + disabled=[self.disabled()]; + @match self.help_text() { + Some(help_text) => div class="form-text" { (help_text) }, + None => {} } } } @@ -126,7 +124,7 @@ impl Date { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -134,7 +132,7 @@ impl Date { self } - pub fn autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -142,7 +140,7 @@ impl Date { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -150,7 +148,7 @@ impl Date { self } - pub fn readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -158,7 +156,7 @@ impl Date { self } - pub fn required(mut self, toggle: bool) -> Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -178,44 +176,44 @@ impl Date { // Date GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn value(&self) -> &str { - self.value.value() + pub fn value(&self) -> &Option { + self.value.option() } - pub fn label(&self) -> &str { - self.label.value() + pub fn label(&self) -> &Option { + self.label.option() } - pub fn placeholder(&self) -> &str { - self.placeholder.value() + pub fn placeholder(&self) -> &Option { + self.placeholder.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() } - pub fn has_autocomplete(&self) -> bool { - !self.autocomplete.has_value() + pub fn autocomplete(&self) -> &Option { + self.autocomplete.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn disabled(&self) -> &Option { + self.disabled.option() } - pub fn is_readonly(&self) -> bool { - self.readonly.has_value() + pub fn readonly(&self) -> &Option { + self.readonly.option() } - pub fn is_required(&self) -> bool { - self.required.has_value() + pub fn required(&self) -> &Option { + self.required.option() } - pub fn help_text(&self) -> &str { - self.help_text.value() + pub fn help_text(&self) -> &Option { + self.help_text.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 385dd369..5ecea5e0 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -7,8 +7,8 @@ pub struct Form { weight : i8, id : OptIden, action : OptAttr, - method : FormMethod, charset : OptAttr, + method : FormMethod, elements : PageContainer, template : String, } @@ -21,8 +21,8 @@ impl PageComponent for Form { weight : 0, id : OptIden::none(), action : OptAttr::none(), - method : FormMethod::Post, charset : OptAttr::some("UTF-8"), + method : FormMethod::Post, elements : PageContainer::new(), template : "default".to_owned(), } @@ -37,19 +37,19 @@ impl PageComponent for Form { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let method = match self.method { + let method = match self.method() { FormMethod::Get => None, FormMethod::Post => Some("post".to_owned()) }; html! { form - id=[&self.id.option()] - action=[&self.action.option()] + id=[self.id()] + action=[self.action()] method=[method] - accept-charset=[&self.charset.option()] + accept-charset=[self.charset()] { div { - (self.elements.render(assets)) + (self.render_elements(assets)) } } } @@ -80,13 +80,13 @@ impl Form { self } - pub fn with_method(mut self, method: FormMethod) -> Self { - self.method = method; + pub fn with_charset(mut self, charset: &str) -> Self { + self.charset.with_value(charset); self } - pub fn with_charset(mut self, charset: &str) -> Self { - self.charset.with_value(charset); + pub fn with_method(mut self, method: FormMethod) -> Self { + self.method = method; self } @@ -102,28 +102,31 @@ impl Form { // Form GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } - pub fn action(&self) -> &str { - self.action.value() + pub fn action(&self) -> &Option { + self.action.option() } - pub fn method(&self) -> &str { - match &self.method { - FormMethod::Get => "get", - FormMethod::Post => "post" - } + pub fn charset(&self) -> &Option { + self.charset.option() } - pub fn charset(&self) -> &str { - self.charset.value() + pub fn method(&self) -> &FormMethod { + &self.method } pub fn template(&self) -> &str { self.template.as_str() } + + // Form EXTRAS. + + pub fn render_elements(&self, assets: &mut PageAssets) -> Markup { + html! { (self.elements.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index b7eca015..636d034e 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -1,18 +1,18 @@ use crate::prelude::*; pub struct Hidden { - weight : i8, - name : OptIden, - value : OptAttr, + weight: i8, + name : OptIden, + value : OptAttr, } impl PageComponent for Hidden { fn new() -> Self { Hidden { - weight : 0, - name : OptIden::none(), - value : OptAttr::none(), + weight: 0, + name : OptIden::none(), + value : OptAttr::none(), } } @@ -21,16 +21,12 @@ impl PageComponent for Hidden { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let id = match self.name.option() { - Some(name) => Some(format!("value-{}", name)), + let id = match self.name() { + Some(name) => Some(concat_string!("value-", name)), _ => None }; html! { - input - type="hidden" - id=[&id] - name=[&self.name.option()] - value=[&self.value.option()]; + input type="hidden" id=[id] name=[self.name()] value=[self.value()]; } } } @@ -60,11 +56,11 @@ impl Hidden { // Hidden GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn value(&self) -> &str { - self.value.value() + pub fn value(&self) -> &Option { + self.value.option() } } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 7622fd08..7dded20f 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -enum InputType {Email, Password, Search, Telephone, Textfield, Url} +pub enum InputType {Email, Password, Search, Telephone, Textfield, Url} pub struct Input { renderable : fn() -> bool, @@ -55,7 +55,7 @@ impl PageComponent for Input { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (type_input, type_class) = match &self.input_type { + let (type_input, type_class) = match self.input_type() { InputType::Email => ("email", "form-type-email"), InputType::Password => ("password", "form-type-password"), InputType::Search => ("search", "form-type-search"), @@ -63,50 +63,48 @@ impl PageComponent for Input { InputType::Textfield => ("text", "form-type-textfield"), InputType::Url => ("url", "form-type-url") }; - let (class, id) = match &self.name.option() { + let (class, id) = match self.name() { Some(name) => ( - format!("form-item form-item-{} {}", name, type_class), - Some(format!("edit-{}", name)) + concat_string!("form-item form-item-", name, " ", type_class), + Some(concat_string!("edit-", name)) ), None => ( - format!("form-item {}", type_class), + concat_string!("form-item ", type_class), None ) }; html! { div class=(class) { - @if self.label.has_value() { - label class="form-label" for=[&id] { - (self.label.value()) " " - @if self.required.has_value() { - span + @match self.label() { + Some(label) => label class="form-label" for=[&id] { + (label) " " + @match self.required() { + Some(_) => span class="form-required" - title="Este campo es obligatorio." - { - "*" - } " " + title="Este campo es obligatorio." { "*" } " ", + None => {} } - } + }, + None => {} } input type=(type_input) - id=[&id] + id=[id] class="form-control" - name=[&self.name.option()] - value=[&self.value.option()] - size=[self.size] - minlength=[self.minlength] - maxlength=[self.maxlength] - placeholder=[&self.placeholder.option()] - autofocus=[&self.autofocus.option()] - autocomplete=[&self.autocomplete.option()] - readonly=[&self.readonly.option()] - required=[&self.required.option()] - disabled=[&self.disabled.option()]; - @if self.help_text.has_value() { - div class="form-text" { - (self.help_text.value()) - } + name=[self.name()] + value=[self.value()] + size=[self.size()] + minlength=[self.minlength()] + maxlength=[self.maxlength()] + placeholder=[self.placeholder()] + autofocus=[self.autofocus()] + autocomplete=[self.autocomplete()] + readonly=[self.readonly()] + required=[self.required()] + disabled=[self.disabled()]; + @match self.help_text() { + Some(help_text) => div class="form-text" { (help_text) }, + None => {} } } } @@ -196,7 +194,7 @@ impl Input { self } - pub fn autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -204,7 +202,7 @@ impl Input { self } - pub fn autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -212,7 +210,7 @@ impl Input { self } - pub fn disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -220,7 +218,7 @@ impl Input { self } - pub fn readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -228,7 +226,7 @@ impl Input { self } - pub fn required(mut self, toggle: bool) -> Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -248,16 +246,20 @@ impl Input { // Input GETTERS. - pub fn name(&self) -> &str { - self.name.value() + pub fn input_type(&self) -> &InputType { + &self.input_type } - pub fn value(&self) -> &str { - self.value.value() + pub fn name(&self) -> &Option { + self.name.option() } - pub fn label(&self) -> &str { - self.label.value() + pub fn value(&self) -> &Option { + self.value.option() + } + + pub fn label(&self) -> &Option { + self.label.option() } pub fn size(&self) -> Option { @@ -272,32 +274,32 @@ impl Input { self.maxlength } - pub fn placeholder(&self) -> &str { - self.placeholder.value() + pub fn placeholder(&self) -> &Option { + self.placeholder.option() } - pub fn has_autofocus(&self) -> bool { - self.autofocus.has_value() + pub fn autofocus(&self) -> &Option { + self.autofocus.option() } - pub fn has_autocomplete(&self) -> bool { - !self.autocomplete.has_value() + pub fn autocomplete(&self) -> &Option { + self.autocomplete.option() } - pub fn is_disabled(&self) -> bool { - self.disabled.has_value() + pub fn disabled(&self) -> &Option { + self.disabled.option() } - pub fn is_readonly(&self) -> bool { - self.readonly.has_value() + pub fn readonly(&self) -> &Option { + self.readonly.option() } - pub fn is_required(&self) -> bool { - self.required.has_value() + pub fn required(&self) -> &Option { + self.required.option() } - pub fn help_text(&self) -> &str { - self.help_text.value() + pub fn help_text(&self) -> &Option { + self.help_text.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/base/component/form/mod.rs index 4e10d476..23b965e9 100644 --- a/pagetop/src/base/component/form/mod.rs +++ b/pagetop/src/base/component/form/mod.rs @@ -2,10 +2,10 @@ mod form; pub use form::{Form, FormMethod}; mod input; -pub use input::Input; +pub use input::{Input, InputType}; mod hidden; pub use hidden::Hidden; mod date; pub use date::Date; mod button; -pub use button::Button; +pub use button::{Button, ButtonType}; diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 19eb577b..6d3a7b19 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -32,8 +32,8 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class=[&self.classes.option()] { - (self.components.render(assets)) + div id=[self.id()] class=[self.classes()] { + (self.render_components(assets)) } } } @@ -75,13 +75,23 @@ impl Column { // Column GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Column EXTRAS. + + pub fn render_components(&self, assets: &mut PageAssets) -> Markup { + html! { (self.components.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 53719e3f..b1bb2c24 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -32,8 +32,8 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[&self.id.option()] class=[&self.classes.option()] { - (self.columns.render(assets)) + div id=[self.id()] class=[self.classes()] { + (self.render_columns(assets)) } } } @@ -75,13 +75,23 @@ impl Row { // Row GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } + + // Row EXTRAS. + + pub fn render_columns(&self, assets: &mut PageAssets) -> Markup { + html! { (self.columns.render(assets)) } + } } fn always() -> bool { diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index b330b374..799aab63 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub struct Image { renderable: fn() -> bool, weight : i8, - source : Option, + source : OptAttr, template : String, } @@ -13,7 +13,7 @@ impl PageComponent for Image { Image { renderable: always, weight : 0, - source : None, + source : OptAttr::none(), template : "default".to_owned(), } } @@ -28,7 +28,7 @@ impl PageComponent for Image { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - img src=[&self.source] class="img-fluid" {} + img src=[self.source()] class="img-fluid"; } } } @@ -36,9 +36,7 @@ impl PageComponent for Image { impl Image { pub fn image(source: &str) -> Self { - let mut i = Image::new(); - i.source = Some(source.to_owned()); - i + Image::new().with_source(source) } // Image BUILDER. @@ -53,6 +51,11 @@ impl Image { self } + pub fn with_source(mut self, source: &str) -> Self { + self.source.with_value(source); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -60,6 +63,10 @@ impl Image { // Image GETTERS. + pub fn source(&self) -> &Option { + self.source.option() + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 0f529874..253cd3d8 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,12 +1,13 @@ use crate::prelude::*; -enum MenuItemType { +pub enum MenuItemType { Label(String), Link(String, String), LinkBlank(String, String), Html(Markup), Separator, Submenu(String, Menu), + Void, } // ----------------------------------------------------------------------------- @@ -16,7 +17,7 @@ enum MenuItemType { pub struct MenuItem { renderable: fn() -> bool, weight : i8, - item_type : Option, + item_type : MenuItemType, } impl PageComponent for MenuItem { @@ -25,7 +26,7 @@ impl PageComponent for MenuItem { MenuItem { renderable: always, weight : 0, - item_type : None, + item_type : MenuItemType::Void, } } @@ -38,22 +39,22 @@ impl PageComponent for MenuItem { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - match &self.item_type { - Some(MenuItemType::Label(label)) => html! { + match self.item_type() { + MenuItemType::Label(label) => html! { li class="label" { a href="#" { (label) } } }, - Some(MenuItemType::Link(label, path)) => html! { + MenuItemType::Link(label, path) => html! { li class="link" { a href=(path) { (label) } } }, - Some(MenuItemType::LinkBlank(label, path)) => html! { + MenuItemType::LinkBlank(label, path) => html! { li class="link_blank" { a href=(path) target="_blank" { (label) } } }, - Some(MenuItemType::Html(html)) => html! { + MenuItemType::Html(html) => html! { li class="html" { (*html) } }, - Some(MenuItemType::Submenu(label, menu)) => html! { + MenuItemType::Submenu(label, menu) => html! { li class="submenu" { a href="#" { (label) } ul { @@ -61,10 +62,10 @@ impl PageComponent for MenuItem { } } }, - Some(MenuItemType::Separator) => html! { + MenuItemType::Separator => html! { li class="separator" { } }, - None => html! {} + MenuItemType::Void => html! {}, } } } @@ -75,7 +76,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Label(label.to_owned())), + item_type : MenuItemType::Label(label.to_owned()), } } @@ -83,10 +84,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Link( + item_type : MenuItemType::Link( label.to_owned(), path.to_owned(), - )), + ), } } @@ -94,10 +95,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::LinkBlank( + item_type : MenuItemType::LinkBlank( label.to_owned(), path.to_owned(), - )), + ), } } @@ -105,7 +106,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Html(html)), + item_type : MenuItemType::Html(html), } } @@ -113,7 +114,7 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Separator), + item_type : MenuItemType::Separator, } } @@ -121,10 +122,10 @@ impl MenuItem { MenuItem { renderable: always, weight : 0, - item_type : Some(MenuItemType::Submenu( + item_type : MenuItemType::Submenu( label.to_owned(), menu - )), + ), } } @@ -139,6 +140,12 @@ impl MenuItem { self.weight = weight; self } + + // MenuItem GETTERS. + + pub fn item_type(&self) -> &MenuItemType { + &self.item_type + } } // ----------------------------------------------------------------------------- @@ -186,7 +193,7 @@ impl PageComponent for Menu { )) .add_jquery(); - let id = assets.serial_id(self.name(), self.id.value()); + let id = assets.serial_id(self.name(), self.id()); html! { ul id=(id) class="sm sm-clean" { (self.render_items(assets)) @@ -232,8 +239,8 @@ impl Menu { // Menu GETTERS. - pub fn id(&self) -> &str { - self.id.value() + pub fn id(&self) -> &Option { + self.id.option() } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index 4619c937..b4e646b9 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -1,5 +1,5 @@ mod container; -pub use container::Container; +pub use container::{Container, ContainerType}; pub mod grid; @@ -10,7 +10,7 @@ pub use block::Block; mod image; pub use image::Image; mod menu; -pub use menu::{Menu, MenuItem}; +pub use menu::{Menu, MenuItem, MenuItemType}; pub mod form; pub use form::{Form, FormMethod}; diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index c9fc9cc0..489b6d3b 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -140,7 +140,7 @@ fn just_visiting() -> Chunck { span { (l("visiting_title")) } - br {} + br; (l("visiting_subtitle")) } p { (l("visiting_text1")) } diff --git a/pagetop/src/html/optattr.rs b/pagetop/src/html/optattr.rs index 3eed9aab..a76f33b7 100644 --- a/pagetop/src/html/optattr.rs +++ b/pagetop/src/html/optattr.rs @@ -19,17 +19,6 @@ impl OptAttr { }; } - pub fn value(&self) -> &str { - match &self.0 { - Some(value) => value.as_str(), - None => "", - } - } - - pub fn has_value(&self) -> bool { - self.0 != None - } - pub fn option(&self) -> &Option { &self.0 } diff --git a/pagetop/src/html/optiden.rs b/pagetop/src/html/optiden.rs index 93caf18a..ec46acf1 100644 --- a/pagetop/src/html/optiden.rs +++ b/pagetop/src/html/optiden.rs @@ -19,17 +19,6 @@ impl OptIden { }; } - pub fn value(&self) -> &str { - match &self.0 { - Some(id) => id.as_str(), - None => "", - } - } - - pub fn has_value(&self) -> bool { - self.0 != None - } - pub fn option(&self) -> &Option { &self.0 } diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 731271d3..42ad192a 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,8 +1,11 @@ +// Exports. + +pub use concat_string::concat_string; +pub use doc_comment::doc_comment; +pub use once_cell::sync::Lazy; + // Local. -pub(crate) use concat_string::concat_string; -pub(crate) use doc_comment::doc_comment; -pub(crate) use once_cell::sync::Lazy; pub(crate) use futures::executor::block_on as run_now; // ----------------------------------------------------------------------------- diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 7c2e9ef3..429c9449 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -3,6 +3,7 @@ // Macros. pub use crate::{ args, + concat_string, theme_static_files, }; diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index ffc566ea..3d42a06f 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, base}; +use crate::{Lazy, base, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; use crate::theme::*; @@ -289,18 +289,19 @@ impl PageAssets { // Assets EXTRAS. - pub fn serial_id(&mut self, prefix: &str, id: &str) -> String { - if id.is_empty() { - let prefix = prefix.trim().replace(" ", "_").to_lowercase(); - let prefix = if prefix.is_empty() { - "prefix".to_owned() - } else { - prefix - }; - self.id_counter += 1; - [prefix, self.id_counter.to_string()].join("-") - } else { - id.to_owned() + pub fn serial_id(&mut self, prefix: &str, id: &Option) -> String { + match id { + Some(id) => id.to_string(), + None => { + let prefix = prefix.trim().replace(" ", "_").to_lowercase(); + let prefix = if prefix.is_empty() { + "prefix".to_owned() + } else { + prefix + }; + self.id_counter += 1; + concat_string!(prefix, "-", self.id_counter.to_string()) + } } } } diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index fedf05e4..50ff3040 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -122,20 +122,20 @@ impl<'a> Page<'a> { // Page GETTERS. - pub fn language(&self) -> &str { - self.language.value() + pub fn language(&self) -> &Option { + self.language.option() } - pub fn direction(&self) -> &str { - self.direction.value() + pub fn direction(&self) -> &Option { + self.direction.option() } - pub fn title(&self) -> &str { - self.title.value() + pub fn title(&self) -> &Option { + self.title.option() } - pub fn description(&self) -> &str { - self.description.value() + pub fn description(&self) -> &Option { + self.description.option() } pub fn body_classes(&mut self) -> &str { @@ -165,7 +165,7 @@ impl<'a> Page<'a> { // Finalmente, renderizar la página. return Ok(html! { (DOCTYPE) - html lang=[&self.language.option()] dir=[&self.direction.option()] { + html lang=[self.language()] dir=[self.direction()] { (head) (body) } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 15f6566e..51b1d4c8 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,4 +1,4 @@ -use crate::app; +use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::response::page::{Favicon, Page, PageAssets, PageComponent}; @@ -28,22 +28,21 @@ pub trait ThemeTrait: Send + Sync { } fn render_page_head(&self, page: &mut Page) -> Markup { - let title = page.title(); - let title = if title.is_empty() { - SETTINGS.app.name.to_owned() - } else { - [SETTINGS.app.name.to_string(), title.to_string()].join(" | ") - }; - let description = page.description(); let viewport = "width=device-width, initial-scale=1, shrink-to-fit=no"; html! { head { meta charset="utf-8"; - title { (title) } + @match page.title() { + Some(t) => title { + (concat_string!(SETTINGS.app.name, " | ", t)) + }, + None => title { (SETTINGS.app.name) } + } - @if !description.is_empty() { - meta name="description" content=(description); + @match page.description() { + Some(d) => meta name="description" content=(d);, + None => {} } meta http-equiv="X-UA-Compatible" content="IE=edge"; From 363cec7a75d0479bf89df8c71a1060b703178084 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 30 Mar 2022 23:48:11 +0200 Subject: [PATCH 14/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- pagetop/src/base/component/block.rs | 40 ++++++++++++++------ pagetop/src/base/component/container.rs | 34 ++++++++++++----- pagetop/src/base/component/form/button.rs | 18 ++++++++- pagetop/src/base/component/form/date.rs | 20 +++++++++- pagetop/src/base/component/form/form.rs | 39 ++++++++++++++------ pagetop/src/base/component/form/input.rs | 16 ++++++++ pagetop/src/base/component/grid/column.rs | 29 ++++++++++----- pagetop/src/base/component/grid/row.rs | 29 ++++++++++----- pagetop/src/base/component/image.rs | 32 +++++++++++++++- pagetop/src/base/component/menu.rs | 26 ++++++++++--- pagetop/src/base/theme/bulmix/mod.rs | 26 +++++++++++++ pagetop/src/html/classes.rs | 45 +++++------------------ pagetop/src/html/optattr.rs | 5 ++- pagetop/src/html/optiden.rs | 5 ++- pagetop/src/response/page/page.rs | 27 ++++++++------ pagetop/src/theme/definition.rs | 6 +-- 17 files changed, 284 insertions(+), 115 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 01eb60ec..8598de96 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.5" +version = "0.0.6" edition = "2021" authors = [ diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 976c27bc..fdf9922d 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -3,9 +3,10 @@ use crate::prelude::*; pub struct Block { renderable: fn() -> bool, weight : i8, - id : OptIden, title : OptAttr, html : Vec, + id : OptIden, + classes : Classes, template : String, } @@ -15,9 +16,10 @@ impl PageComponent for Block { Block { renderable: always, weight : 0, - id : OptIden::none(), title : OptAttr::none(), html : Vec::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -33,7 +35,7 @@ impl PageComponent for Block { fn default_render(&self, assets: &mut PageAssets) -> Markup { let id = assets.serial_id(self.name(), self.id()); html! { - div id=(id) class="block" { + div id=(id) class=[self.classes("block")] { @match self.title() { Some(title) => h2 class="block-title" { (title) }, None => {} @@ -66,11 +68,6 @@ impl Block { self } - pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); - self - } - pub fn with_title(mut self, title: &str) -> Self { self.title.with_value(title); self @@ -81,6 +78,21 @@ impl Block { self } + pub fn with_id(mut self, id: &str) -> Self { + self.id.with_value(id); + self + } + + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -88,10 +100,6 @@ impl Block { // Block GETTERS. - pub fn id(&self) -> &Option { - self.id.option() - } - pub fn title(&self) -> &Option { self.title.option() } @@ -100,6 +108,14 @@ impl Block { &self.html } + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index cba905d6..94003ae0 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -6,8 +6,9 @@ pub struct Container { renderable: fn() -> bool, weight : i8, container : ContainerType, - id : OptIden, components: PageContainer, + id : OptIden, + classes : Classes, template : String, } @@ -18,8 +19,9 @@ impl PageComponent for Container { renderable: always, weight : 0, container : ContainerType::Wrapper, - id : OptIden::none(), components: PageContainer::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -35,35 +37,35 @@ impl PageComponent for Container { fn default_render(&self, assets: &mut PageAssets) -> Markup { match self.container_type() { ContainerType::Header => html! { - header id=[self.id()] class="header" { + header id=[self.id()] class=[self.classes("header")] { div class="container" { (self.render_components(assets)) } } }, ContainerType::Footer => html! { - footer id=[self.id()] class="footer" { + footer id=[self.id()] class=[self.classes("footer")] { div class="container" { (self.render_components(assets)) } } }, ContainerType::Main => html! { - main id=[self.id()] class="main" { + main id=[self.id()] class=[self.classes("main")] { div class="container" { (self.render_components(assets)) } } }, ContainerType::Section => html! { - section id=[self.id()] class="section" { + section id=[self.id()] class=[self.classes("section")] { div class="container" { (self.render_components(assets)) } } }, _ => html! { - div id=[self.id()] class="container" { + div id=[self.id()] class=[self.classes("container")] { (self.render_components(assets)) } } @@ -109,13 +111,23 @@ impl Container { self } + pub fn add(mut self, component: impl PageComponent) -> Self { + self.components.add(component); + self + } + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn add(mut self, component: impl PageComponent) -> Self { - self.components.add(component); + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); self } @@ -134,6 +146,10 @@ impl Container { self.id.option() } + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index fbe25738..b2f59609 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -10,6 +10,7 @@ pub struct Button { value : OptAttr, autofocus : OptAttr, disabled : OptAttr, + classes : Classes, template : String, } @@ -24,6 +25,7 @@ impl PageComponent for Button { value : OptAttr::none(), autofocus : OptAttr::none(), disabled : OptAttr::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -50,7 +52,7 @@ impl PageComponent for Button { button type=(button_type) id=[id] - class=(button_class) + class=[self.classes(button_class)] name=[self.name()] value=[self.value()] autofocus=[self.autofocus()] @@ -121,6 +123,16 @@ impl Button { self } + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -148,6 +160,10 @@ impl Button { self.disabled.option() } + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 906f5bbc..f1270a82 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -13,6 +13,7 @@ pub struct Date { readonly : OptAttr, required : OptAttr, help_text : OptAttr, + classes : Classes, template : String, } @@ -32,6 +33,7 @@ impl PageComponent for Date { readonly : OptAttr::none(), required : OptAttr::none(), help_text : OptAttr::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -45,7 +47,7 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (class, id) = match self.name() { + let (classes, id) = match self.name() { Some(name) => ( concat_string!("form-item form-item-", name, " form-type-date"), Some(concat_string!("edit-", name)) @@ -56,7 +58,7 @@ impl PageComponent for Date { ) }; html! { - div class=(class) { + div class=[self.classes(classes.as_str())] { @match self.label() { Some(label) => label class="form-label" for=[&id] { (label) " " @@ -169,6 +171,16 @@ impl Date { self } + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -216,6 +228,10 @@ impl Date { self.help_text.option() } + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 5ecea5e0..c4d8e206 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -5,11 +5,12 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : i8, - id : OptIden, action : OptAttr, charset : OptAttr, method : FormMethod, elements : PageContainer, + id : OptIden, + classes : Classes, template : String, } @@ -19,11 +20,12 @@ impl PageComponent for Form { Form { renderable: always, weight : 0, - id : OptIden::none(), action : OptAttr::none(), charset : OptAttr::some("UTF-8"), method : FormMethod::Post, elements : PageContainer::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -44,6 +46,7 @@ impl PageComponent for Form { html! { form id=[self.id()] + class=[self.classes("form")] action=[self.action()] method=[method] accept-charset=[self.charset()] @@ -70,11 +73,6 @@ impl Form { self } - pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); - self - } - pub fn with_action(mut self, action: &str) -> Self { self.action.with_value(action); self @@ -95,6 +93,21 @@ impl Form { self } + pub fn with_id(mut self, id: &str) -> Self { + self.id.with_value(id); + self + } + + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -102,10 +115,6 @@ impl Form { // Form GETTERS. - pub fn id(&self) -> &Option { - self.id.option() - } - pub fn action(&self) -> &Option { self.action.option() } @@ -118,6 +127,14 @@ impl Form { &self.method } + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 7dded20f..2e1af61d 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -19,6 +19,7 @@ pub struct Input { readonly : OptAttr, required : OptAttr, help_text : OptAttr, + classes : Classes, template : String, } @@ -42,6 +43,7 @@ impl PageComponent for Input { readonly : OptAttr::none(), required : OptAttr::none(), help_text : OptAttr::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -239,6 +241,16 @@ impl Input { self } + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -302,6 +314,10 @@ impl Input { self.help_text.option() } + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 6d3a7b19..f5bc4669 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -3,9 +3,9 @@ use crate::prelude::*; pub struct Column { renderable: fn() -> bool, weight : i8, + components: PageContainer, id : OptIden, classes : Classes, - components: PageContainer, template : String, } @@ -15,13 +15,17 @@ impl PageComponent for Column { Column { renderable: always, weight : 0, - id : OptIden::none(), - classes : Classes::some(vec!["col"]), components: PageContainer::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } + fn name(&self) -> &'static str { + "GridColumn" + } + fn is_renderable(&self) -> bool { (self.renderable)() } @@ -32,7 +36,7 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[self.id()] class=[self.classes()] { + div id=[self.id()] class=[self.classes("col")] { (self.render_components(assets)) } } @@ -53,18 +57,23 @@ impl Column { self } + pub fn add(mut self, component: impl PageComponent) -> Self { + self.components.add(component); + self + } + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn add_classes(mut self, classes: Vec<&str>) -> Self { - self.classes.add_classes(classes); + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); self } - pub fn add(mut self, component: impl PageComponent) -> Self { - self.components.add(component); + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); self } @@ -79,8 +88,8 @@ impl Column { self.id.option() } - pub fn classes(&self) -> &Option { - self.classes.option() + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index b1bb2c24..8437c1fe 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -3,9 +3,9 @@ use crate::prelude::*; pub struct Row { renderable: fn() -> bool, weight : i8, + columns : PageContainer, id : OptIden, classes : Classes, - columns : PageContainer, template : String, } @@ -15,13 +15,17 @@ impl PageComponent for Row { Row { renderable: always, weight : 0, - id : OptIden::none(), - classes : Classes::some(vec!["row"]), columns : PageContainer::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } + fn name(&self) -> &'static str { + "GridRow" + } + fn is_renderable(&self) -> bool { (self.renderable)() } @@ -32,7 +36,7 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[self.id()] class=[self.classes()] { + div id=[self.id()] class=[self.classes("row")] { (self.render_columns(assets)) } } @@ -53,18 +57,23 @@ impl Row { self } + pub fn add_column(mut self, column: grid::Column) -> Self { + self.columns.add(column); + self + } + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn add_classes(mut self, classes: Vec<&str>) -> Self { - self.classes.add_classes(classes); + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); self } - pub fn add_column(mut self, column: grid::Column) -> Self { - self.columns.add(column); + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); self } @@ -79,8 +88,8 @@ impl Row { self.id.option() } - pub fn classes(&self) -> &Option { - self.classes.option() + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) } pub fn template(&self) -> &str { diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 799aab63..c324782a 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -4,6 +4,8 @@ pub struct Image { renderable: fn() -> bool, weight : i8, source : OptAttr, + id : OptIden, + classes : Classes, template : String, } @@ -14,6 +16,8 @@ impl PageComponent for Image { renderable: always, weight : 0, source : OptAttr::none(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -28,7 +32,10 @@ impl PageComponent for Image { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { - img src=[self.source()] class="img-fluid"; + img + src=[self.source()] + id=[self.id()] + class=[self.classes("img-fluid")]; } } } @@ -56,6 +63,21 @@ impl Image { self } + pub fn with_id(mut self, id: &str) -> Self { + self.id.with_value(id); + self + } + + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); + self + } + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self @@ -67,6 +89,14 @@ impl Image { self.source.option() } + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 253cd3d8..91881908 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -155,8 +155,9 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, weight : i8, - id : OptIden, items : PageContainer, + id : OptIden, + classes : Classes, template : String, } @@ -166,8 +167,9 @@ impl PageComponent for Menu { Menu { renderable: always, weight : 0, - id : OptIden::none(), items : PageContainer::new(), + id : OptIden::none(), + classes : Classes::none(), template : "default".to_owned(), } } @@ -195,7 +197,7 @@ impl PageComponent for Menu { let id = assets.serial_id(self.name(), self.id()); html! { - ul id=(id) class="sm sm-clean" { + ul id=(id) class=[self.classes("sm sm-clean")] { (self.render_items(assets)) } script type="text/javascript" defer { @@ -222,13 +224,23 @@ impl Menu { self } + pub fn add(mut self, item: MenuItem) -> Self { + self.items.add(item); + self + } + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn add(mut self, item: MenuItem) -> Self { - self.items.add(item); + pub fn set_classes(mut self, classes: &str) -> Self { + self.classes.set_classes(classes); + self + } + + pub fn add_classes(mut self, classes: &str) -> Self { + self.classes.add_classes(classes); self } @@ -243,6 +255,10 @@ impl Menu { self.id.option() } + pub fn classes(&self, default: &str) -> Option { + self.classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index b8d57ba7..0e8a4d9b 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -31,4 +31,30 @@ impl ThemeTrait for BulmixTheme { ) .add_jquery(); } + + fn render_component( + &self, + component: &dyn PageComponent, + assets: &mut PageAssets + ) -> Option { + match component.name() { + "GridRow" => { + let row = component.downcast_ref::().unwrap(); + Some(html! { + div id=[row.id()] class=[row.classes("columns")] { + (row.render_columns(assets)) + } + }) + }, + "GridColumn" => { + let col = component.downcast_ref::().unwrap(); + Some(html! { + div id=[col.id()] class=[col.classes("column")] { + (col.render_components(assets)) + } + }) + }, + _ => None + } + } } diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index c2a35984..6c41aafb 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -1,48 +1,23 @@ use crate::concat_string; -pub struct Classes(Option); +pub struct Classes(String); impl Classes { pub fn none() -> Self { - Classes(None) + Classes("".to_owned()) } - pub fn some(classes: Vec<&str>) -> Self { - let mut c = Classes::none(); - c.add_classes(classes); - c + pub fn set_classes(&mut self, classes: &str) -> &mut Self { + self.0 = classes.to_owned(); + self } - pub fn add_classes(&mut self, classes: Vec<&str>) { - for class in classes.iter() { - self.add_class(class); - } + pub fn add_classes(&mut self, classes: &str) -> &mut Self { + self.0 = concat_string!(self.0, " ", classes).trim().to_owned(); + self } - fn add_class(&mut self, class: &str) { - let class = class.trim().replace(" ", "_"); - if !class.is_empty() { - match &self.0 { - None => self.0 = Some(class), - Some(classes) => if !classes.split(" ").any(|c| *c == class) { - self.0 = Some(concat_string!(classes, " ", class)) - } - } - } - } - - pub fn classes(&self) -> &str { - match &self.0 { - Some(classes) => classes.as_str(), - None => "", - } - } - - pub fn has_classes(&self) -> bool { - self.0 != None - } - - pub fn option(&self) -> &Option { - &self.0 + pub fn option(&self, default: &str) -> Option { + Some(concat_string!(default.to_owned(), " ", self.0).trim().to_owned()) } } diff --git a/pagetop/src/html/optattr.rs b/pagetop/src/html/optattr.rs index a76f33b7..d009e32e 100644 --- a/pagetop/src/html/optattr.rs +++ b/pagetop/src/html/optattr.rs @@ -6,17 +6,18 @@ impl OptAttr { } pub fn some(value: &str) -> Self { - let mut o = OptAttr::none(); + let mut o = OptAttr(None); o.with_value(value); o } - pub fn with_value(&mut self, value: &str) { + pub fn with_value(&mut self, value: &str) -> &mut Self { let value = value.trim(); self.0 = match value.is_empty() { true => None, false => Some(value.to_owned()), }; + self } pub fn option(&self) -> &Option { diff --git a/pagetop/src/html/optiden.rs b/pagetop/src/html/optiden.rs index ec46acf1..52a65c10 100644 --- a/pagetop/src/html/optiden.rs +++ b/pagetop/src/html/optiden.rs @@ -6,17 +6,18 @@ impl OptIden { } pub fn some(id: &str) -> Self { - let mut o = OptIden::none(); + let mut o = OptIden(None); o.with_value(id); o } - pub fn with_value(&mut self, id: &str) { + pub fn with_value(&mut self, id: &str) -> &mut Self { let id = id.trim(); self.0 = match id.is_empty() { true => None, false => Some(id.replace(" ", "_")), }; + self } pub fn option(&self) -> &Option { diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 50ff3040..cb561626 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -45,8 +45,8 @@ pub struct Page<'a> { title : OptAttr, description : OptAttr, assets : PageAssets, - body_classes: Classes, regions : HashMap<&'a str, PageContainer>, + body_classes: Classes, template : String, } @@ -64,9 +64,9 @@ impl<'a> Page<'a> { }, title : OptAttr::none(), description : OptAttr::none(), - body_classes: Classes::some(vec!["body"]), assets : PageAssets::new(), regions : COMPONENTS.read().unwrap().clone(), + body_classes: Classes::none(), template : "default".to_owned(), } } @@ -97,11 +97,6 @@ impl<'a> Page<'a> { self } - pub fn add_body_classes(&mut self, classes: Vec<&str>) -> &mut Self { - self.body_classes.add_classes(classes); - self - } - pub fn add_to( &mut self, region: &'a str, @@ -115,6 +110,16 @@ impl<'a> Page<'a> { self } + pub fn set_body_classes(&mut self, classes: &str) -> &mut Self { + self.body_classes.set_classes(classes); + self + } + + pub fn add_body_classes(&mut self, classes: &str) -> &mut Self { + self.body_classes.add_classes(classes); + self + } + pub fn using_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self @@ -138,14 +143,14 @@ impl<'a> Page<'a> { self.description.option() } - pub fn body_classes(&mut self) -> &str { - self.body_classes.classes() - } - pub fn assets(&mut self) -> &mut PageAssets { &mut self.assets } + pub fn body_classes(&self, default: &str) -> Option { + self.body_classes.option(default) + } + pub fn template(&self) -> &str { self.template.as_str() } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 51b1d4c8..acc30f47 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -55,7 +55,7 @@ pub trait ThemeTrait: Send + Sync { fn render_page_body(&self, page: &mut Page) -> Markup { html! { - body class=(page.body_classes()) { + body class=[page.body_classes("body")] { @match page.template() { "admin" => { @for region in &["top-menu", "side-menu", "content"] { @@ -85,8 +85,8 @@ pub trait ThemeTrait: Send + Sync { Cómo usarlo: match component.name() { - "block" => { - let block = component.downcast_mut::().unwrap(); + "Block" => { + let block = component.downcast_ref::().unwrap(); match block.template() { "default" => Some(block_default(block)), _ => None From 48fa9e9db9b4c3b5f564c828bb33891e30fd7842 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 31 Mar 2022 00:50:53 +0200 Subject: [PATCH 15/80] Modifica el renderizado de contenedores internos --- pagetop/src/base/component/container.rs | 20 +++++++++----------- pagetop/src/base/component/form/form.rs | 14 +++++--------- pagetop/src/base/component/menu.rs | 14 ++++++-------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 94003ae0..24172d00 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -39,34 +39,34 @@ impl PageComponent for Container { ContainerType::Header => html! { header id=[self.id()] class=[self.classes("header")] { div class="container" { - (self.render_components(assets)) + (self.components().render(assets)) } } }, ContainerType::Footer => html! { footer id=[self.id()] class=[self.classes("footer")] { div class="container" { - (self.render_components(assets)) + (self.components().render(assets)) } } }, ContainerType::Main => html! { main id=[self.id()] class=[self.classes("main")] { div class="container" { - (self.render_components(assets)) + (self.components().render(assets)) } } }, ContainerType::Section => html! { section id=[self.id()] class=[self.classes("section")] { div class="container" { - (self.render_components(assets)) + (self.components().render(assets)) } } }, _ => html! { div id=[self.id()] class=[self.classes("container")] { - (self.render_components(assets)) + (self.components().render(assets)) } } } @@ -142,6 +142,10 @@ impl Container { &self.container } + pub fn components(&self) -> &PageContainer { + &self.components + } + pub fn id(&self) -> &Option { self.id.option() } @@ -153,12 +157,6 @@ impl Container { pub fn template(&self) -> &str { self.template.as_str() } - - // Container EXTRAS. - - pub fn render_components(&self, assets: &mut PageAssets) -> Markup { - html! { (self.components.render(assets)) } - } } fn always() -> bool { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index c4d8e206..2d88d141 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -51,9 +51,7 @@ impl PageComponent for Form { method=[method] accept-charset=[self.charset()] { - div { - (self.render_elements(assets)) - } + div { (self.elements().render(assets)) } } } } @@ -127,6 +125,10 @@ impl Form { &self.method } + pub fn elements(&self) -> &PageContainer { + &self.elements + } + pub fn id(&self) -> &Option { self.id.option() } @@ -138,12 +140,6 @@ impl Form { pub fn template(&self) -> &str { self.template.as_str() } - - // Form EXTRAS. - - pub fn render_elements(&self, assets: &mut PageAssets) -> Markup { - html! { (self.elements.render(assets)) } - } } fn always() -> bool { diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 91881908..85b9007e 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -58,7 +58,7 @@ impl PageComponent for MenuItem { li class="submenu" { a href="#" { (label) } ul { - (menu.render_items(assets)) + (menu.items().render(assets)) } } }, @@ -198,7 +198,7 @@ impl PageComponent for Menu { let id = assets.serial_id(self.name(), self.id()); html! { ul id=(id) class=[self.classes("sm sm-clean")] { - (self.render_items(assets)) + (self.items().render(assets)) } script type="text/javascript" defer { "jQuery(function(){jQuery('#" (id) "').smartmenus({" @@ -251,6 +251,10 @@ impl Menu { // Menu GETTERS. + pub fn items(&self) -> &PageContainer { + &self.items + } + pub fn id(&self) -> &Option { self.id.option() } @@ -262,12 +266,6 @@ impl Menu { pub fn template(&self) -> &str { self.template.as_str() } - - // Menu EXTRAS. - - pub fn render_items(&self, assets: &mut PageAssets) -> Markup { - html! { (self.items.render(assets)) } - } } fn always() -> bool { From cc579add5fecee236702fc9cab63b5ae5b9fb84c Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 31 Mar 2022 21:05:54 +0200 Subject: [PATCH 16/80] Corrige API del grid --- pagetop/src/base/component/grid/column.rs | 12 +++++------- pagetop/src/base/component/grid/row.rs | 12 +++++------- pagetop/src/base/theme/bulmix/mod.rs | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index f5bc4669..da1a76a9 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -37,7 +37,7 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { div id=[self.id()] class=[self.classes("col")] { - (self.render_components(assets)) + (self.components().render(assets)) } } } @@ -84,6 +84,10 @@ impl Column { // Column GETTERS. + pub fn components(&self) -> &PageContainer { + &self.components + } + pub fn id(&self) -> &Option { self.id.option() } @@ -95,12 +99,6 @@ impl Column { pub fn template(&self) -> &str { self.template.as_str() } - - // Column EXTRAS. - - pub fn render_components(&self, assets: &mut PageAssets) -> Markup { - html! { (self.components.render(assets)) } - } } fn always() -> bool { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 8437c1fe..f4a5b6a5 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -37,7 +37,7 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { div id=[self.id()] class=[self.classes("row")] { - (self.render_columns(assets)) + (self.columns().render(assets)) } } } @@ -84,6 +84,10 @@ impl Row { // Row GETTERS. + pub fn columns(&self) -> &PageContainer { + &self.columns + } + pub fn id(&self) -> &Option { self.id.option() } @@ -95,12 +99,6 @@ impl Row { pub fn template(&self) -> &str { self.template.as_str() } - - // Row EXTRAS. - - pub fn render_columns(&self, assets: &mut PageAssets) -> Markup { - html! { (self.columns.render(assets)) } - } } fn always() -> bool { diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 0e8a4d9b..284353c1 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -42,7 +42,7 @@ impl ThemeTrait for BulmixTheme { let row = component.downcast_ref::().unwrap(); Some(html! { div id=[row.id()] class=[row.classes("columns")] { - (row.render_columns(assets)) + (row.columns().render(assets)) } }) }, @@ -50,7 +50,7 @@ impl ThemeTrait for BulmixTheme { let col = component.downcast_ref::().unwrap(); Some(html! { div id=[col.id()] class=[col.classes("column")] { - (col.render_components(assets)) + (col.components().render(assets)) } }) }, From 69139f2a624545c5959bd748dd9f4cad757f47f2 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 1 Apr 2022 19:15:01 +0200 Subject: [PATCH 17/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/block.rs | 2 -- pagetop/src/base/component/chunck.rs | 2 -- pagetop/src/base/component/container.rs | 2 -- pagetop/src/base/component/form/button.rs | 2 -- pagetop/src/base/component/form/date.rs | 1 - pagetop/src/base/component/form/form.rs | 1 - pagetop/src/base/component/form/hidden.rs | 2 -- pagetop/src/base/component/form/input.rs | 2 -- pagetop/src/base/component/grid/column.rs | 1 - pagetop/src/base/component/grid/row.rs | 1 - pagetop/src/base/component/image.rs | 2 -- pagetop/src/base/component/menu.rs | 3 --- 12 files changed, 21 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index fdf9922d..a1bf8745 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -11,7 +11,6 @@ pub struct Block { } impl PageComponent for Block { - fn new() -> Self { Block { renderable: always, @@ -51,7 +50,6 @@ impl PageComponent for Block { } impl Block { - pub fn with(html: Markup) -> Self { Block::new().add(html) } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 532584fc..dc909a89 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -8,7 +8,6 @@ pub struct Chunck { } impl PageComponent for Chunck { - fn new() -> Self { Chunck { renderable: always, @@ -36,7 +35,6 @@ impl PageComponent for Chunck { } impl Chunck { - pub fn with(html: Markup) -> Self { Chunck::new().add(html) } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 24172d00..b85288af 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -13,7 +13,6 @@ pub struct Container { } impl PageComponent for Container { - fn new() -> Self { Container { renderable: always, @@ -74,7 +73,6 @@ impl PageComponent for Container { } impl Container { - pub fn header() -> Self { let mut c = Container::new(); c.container = ContainerType::Header; diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index b2f59609..f99f06d3 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -15,7 +15,6 @@ pub struct Button { } impl PageComponent for Button { - fn new() -> Self { Button { renderable : always, @@ -68,7 +67,6 @@ impl PageComponent for Button { } impl Button { - pub fn button(value: &str) -> Self { Button::new().with_value(value) } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index f1270a82..40c2f784 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -18,7 +18,6 @@ pub struct Date { } impl PageComponent for Date { - fn new() -> Self { Date { renderable : always, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 2d88d141..e5169ff3 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -15,7 +15,6 @@ pub struct Form { } impl PageComponent for Form { - fn new() -> Self { Form { renderable: always, diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 636d034e..f4734ba0 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -7,7 +7,6 @@ pub struct Hidden { } impl PageComponent for Hidden { - fn new() -> Self { Hidden { weight: 0, @@ -32,7 +31,6 @@ impl PageComponent for Hidden { } impl Hidden { - pub fn set(name: &str, value: &str) -> Self { Hidden::new().with_name(name).with_value(value) } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 2e1af61d..9d6e1afd 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -24,7 +24,6 @@ pub struct Input { } impl PageComponent for Input { - fn new() -> Self { Input { renderable : always, @@ -114,7 +113,6 @@ impl PageComponent for Input { } impl Input { - pub fn textfield() -> Self { Input::new() } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index da1a76a9..c8594642 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -10,7 +10,6 @@ pub struct Column { } impl PageComponent for Column { - fn new() -> Self { Column { renderable: always, diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index f4a5b6a5..03a39e39 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -10,7 +10,6 @@ pub struct Row { } impl PageComponent for Row { - fn new() -> Self { Row { renderable: always, diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index c324782a..1384f4df 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -10,7 +10,6 @@ pub struct Image { } impl PageComponent for Image { - fn new() -> Self { Image { renderable: always, @@ -41,7 +40,6 @@ impl PageComponent for Image { } impl Image { - pub fn image(source: &str) -> Self { Image::new().with_source(source) } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 85b9007e..daabdd60 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -21,7 +21,6 @@ pub struct MenuItem { } impl PageComponent for MenuItem { - fn new() -> Self { MenuItem { renderable: always, @@ -71,7 +70,6 @@ impl PageComponent for MenuItem { } impl MenuItem { - pub fn label(label: &str) -> Self { MenuItem { renderable: always, @@ -162,7 +160,6 @@ pub struct Menu { } impl PageComponent for Menu { - fn new() -> Self { Menu { renderable: always, From 53dd1f24c7cffe369be70aa71b90e8fe44d64f6f Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 2 Apr 2022 09:21:43 +0200 Subject: [PATCH 18/80] =?UTF-8?q?A=C3=B1ade=20la=20funci=C3=B3n=20arc()=20?= =?UTF-8?q?para=20capturar=20el=20componente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recibe un componente mutable que podría modificarse justo antes de ser añadido a un contenedor. Es una posible solución para poder desarrollar un mecanismo aceptable de Triggers/Hooks/Actions (THA) para PageTop. --- pagetop-admin/src/summary.rs | 7 +++--- pagetop-user/src/lib.rs | 8 +++++-- pagetop/src/base/component/container.rs | 2 +- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/base/component/grid/column.rs | 2 +- pagetop/src/base/component/grid/row.rs | 2 +- pagetop/src/base/component/menu.rs | 2 +- pagetop/src/base/module/demopage/mod.rs | 28 ++++++++++++----------- pagetop/src/base/theme/bootsier/mod.rs | 2 +- pagetop/src/response/page/component.rs | 9 ++++++++ pagetop/src/response/page/container.rs | 12 ++++------ pagetop/src/response/page/mod.rs | 2 +- pagetop/src/response/page/page.rs | 6 ++--- pagetop/src/theme/definition.rs | 2 +- 14 files changed, 50 insertions(+), 36 deletions(-) diff --git a/pagetop-admin/src/summary.rs b/pagetop-admin/src/summary.rs index b91b97fa..6e6f2158 100644 --- a/pagetop-admin/src/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -38,17 +38,18 @@ pub async fn summary() -> app::Result { .with_title("Admin") - .add_to("top-menu", top_menu) + .add_to("top-menu", top_menu.arc()) .add_to("content", grid::Row::new() .add_column(grid::Column::new() - .add(side_menu) + .add(side_menu.arc()) ) .add_column(grid::Column::new() .add(Chunck::with(html! { p { "Columna 2"} - })) + }).arc()) ) + .arc() ) diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index dd0b362b..414fb3e4 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -31,7 +31,7 @@ impl ModuleTrait for UserModule { } } -fn form_login() -> impl PageComponent { +fn form_login() -> ArcComponent { Form::new() .with_id("user-login") .add(form::Input::textfield() @@ -41,13 +41,16 @@ fn form_login() -> impl PageComponent { "app" => SETTINGS.app.name.to_owned() ]).as_str()) .with_autofocus(true) + .arc() ) .add(form::Input::password() .with_name("pass") .with_label(l("password").as_str()) .with_help_text(l("password_help").as_str()) + .arc() ) - .add(form::Button::submit(l("login").as_str())) + .add(form::Button::submit(l("login").as_str()).arc()) + .arc() } async fn login() -> app::Result { @@ -58,6 +61,7 @@ async fn login() -> app::Result { .add_to("content", Container::new() .with_id("welcome") .add(form_login()) + .arc() ) .render() } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index b85288af..2e48ba10 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -109,7 +109,7 @@ impl Container { self } - pub fn add(mut self, component: impl PageComponent) -> Self { + pub fn add(mut self, component: ArcComponent) -> Self { self.components.add(component); self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index e5169ff3..9317f9eb 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -85,7 +85,7 @@ impl Form { self } - pub fn add(mut self, element: impl PageComponent) -> Self { + pub fn add(mut self, element: ArcComponent) -> Self { self.elements.add(element); self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index c8594642..a007c83b 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -56,7 +56,7 @@ impl Column { self } - pub fn add(mut self, component: impl PageComponent) -> Self { + pub fn add(mut self, component: ArcComponent) -> Self { self.components.add(component); self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 03a39e39..2a185894 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -57,7 +57,7 @@ impl Row { } pub fn add_column(mut self, column: grid::Column) -> Self { - self.columns.add(column); + self.columns.add(column.arc()); self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index daabdd60..3f2b4ff4 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -222,7 +222,7 @@ impl Menu { } pub fn add(mut self, item: MenuItem) -> Self { - self.items.add(item); + self.items.add(item.arc()); self } diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 489b6d3b..d71c7176 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -35,7 +35,7 @@ async fn demo() -> app::Result { .render() } -fn hello_world() -> Container { +fn hello_world() -> ArcComponent { Container::header() .add(grid::Row::new() .add_column(grid::Column::new() @@ -68,15 +68,17 @@ fn hello_world() -> Container { i class="fas fa-paper-plane" {} "Get quote" } - })) + }).arc()) ) .add_column(grid::Column::new() - .add(Image::image("/bootsier/images/demo-header.svg")) + .add(Image::image("/bootsier/images/demo-header.svg").arc()) ) + .arc() ) + .arc() } -fn hello_world_original() -> Chunck { +fn hello_world_original() -> ArcComponent { Chunck::with(html! { header id="header" class="header" { div class="container" { @@ -121,10 +123,10 @@ fn hello_world_original() -> Chunck { } } } - }) + }).arc() } -fn just_visiting() -> Chunck { +fn just_visiting() -> ArcComponent { Chunck::with(html! { div id="details" class="basic-1" { div class="container" { @@ -151,10 +153,10 @@ fn just_visiting() -> Chunck { } } } - }) + }).arc() } -fn about_pagetop() -> Chunck { +fn about_pagetop() -> ArcComponent { Chunck::with(html! { div id="pagetop" class="basic-2" { div class="container" { @@ -175,10 +177,10 @@ fn about_pagetop() -> Chunck { } } } - }) + }).arc() } -fn promo_pagetop() -> Chunck { +fn promo_pagetop() -> ArcComponent { Chunck::with(html! { div id="promo" class="basic-3" { div class="container" { @@ -200,10 +202,10 @@ fn promo_pagetop() -> Chunck { } } } - }) + }).arc() } -fn reporting_problems() -> Chunck { +fn reporting_problems() -> ArcComponent { Chunck::with(html! { div id="reporting" class="basic-4" { div class="container" { @@ -223,5 +225,5 @@ fn reporting_problems() -> Chunck { } } } - }) + }).arc() } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index 90111723..b169351d 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -77,7 +77,7 @@ impl ThemeTrait for BootsierTheme { } } } - })) + }).arc()) .render() } } diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 630b8a9b..b9a920d3 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -3,8 +3,11 @@ use crate::response::page::PageAssets; use downcast_rs::{Downcast, impl_downcast}; +use std::sync::Arc; use std::any::type_name; +pub type ArcComponent = Arc; + pub trait PageComponent: Downcast + Send + Sync { fn new() -> Self where Self: Sized; @@ -33,6 +36,12 @@ pub trait PageComponent: Downcast + Send + Sync { 0 } + #[allow(unused_mut)] + fn arc(mut self) -> ArcComponent where Self: Sized { + let component = self; + Arc::new(component) + } + #[allow(unused_variables)] fn default_render(&self, assets: &mut PageAssets) -> Markup { html! {} diff --git a/pagetop/src/response/page/container.rs b/pagetop/src/response/page/container.rs index 72287560..7e5d4953 100644 --- a/pagetop/src/response/page/container.rs +++ b/pagetop/src/response/page/container.rs @@ -1,24 +1,22 @@ use crate::html::{Markup, html}; -use crate::response::page::{PageAssets, PageComponent, render_component}; - -use std::sync::Arc; +use crate::response::page::{ArcComponent, PageAssets, render_component}; #[derive(Clone)] -pub struct PageContainer(Vec>); +pub struct PageContainer(Vec); impl PageContainer { pub fn new() -> Self { PageContainer(Vec::new()) } - pub fn new_with(component: impl PageComponent) -> Self { + pub fn new_with(component: ArcComponent) -> Self { let mut container = PageContainer::new(); container.add(component); container } - pub fn add(&mut self, component: impl PageComponent) { - self.0.push(Arc::new(component)); + pub fn add(&mut self, component: ArcComponent) { + self.0.push(component); } pub fn render(&self, assets: &mut PageAssets) -> Markup { diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index f34070e2..63c19a47 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -7,7 +7,7 @@ pub use assets::{ }; mod component; -pub use component::PageComponent; +pub use component::{ArcComponent, PageComponent}; mod container; pub use container::PageContainer; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index cb561626..5cbe80cb 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,7 +1,7 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html}; -use crate::response::page::{PageAssets, PageComponent, PageContainer}; +use crate::response::page::*; use std::sync::RwLock; use std::collections::HashMap; @@ -100,7 +100,7 @@ impl<'a> Page<'a> { pub fn add_to( &mut self, region: &'a str, - component: impl PageComponent + component: ArcComponent ) -> &mut Self { if let Some(regions) = self.regions.get_mut(region) { regions.add(component); @@ -205,7 +205,7 @@ pub fn render_component( } } -pub fn add_component_to(region: &'static str, component: impl PageComponent) { +pub fn add_component_to(region: &'static str, component: ArcComponent) { let mut hmap = COMPONENTS.write().unwrap(); if let Some(regions) = hmap.get_mut(region) { regions.add(component); diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index acc30f47..db4c0e37 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -104,7 +104,7 @@ pub trait ThemeTrait: Send + Sync { div { h1 { (s) } } - })) + }).arc()) .render() } } From 4dd57eab4360f56a57f1caac1a4f2e69a2108cfa Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 4 Apr 2022 20:32:37 +0200 Subject: [PATCH 19/80] =?UTF-8?q?A=C3=B1ade=20referencias=20a=20todos=20lo?= =?UTF-8?q?s=20m=C3=A9todos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El proyecto compila, pendiente de una solución para los contenedores. --- pagetop-user/src/lib.rs | 8 ++--- pagetop/src/base/component/block.rs | 20 +++++++------ pagetop/src/base/component/chunck.rs | 12 ++++---- pagetop/src/base/component/container.rs | 12 ++++---- pagetop/src/base/component/form/button.rs | 28 ++++++++++-------- pagetop/src/base/component/form/date.rs | 30 +++++++++---------- pagetop/src/base/component/form/form.rs | 18 ++++++------ pagetop/src/base/component/form/hidden.rs | 11 ++++--- pagetop/src/base/component/form/input.rs | 36 +++++++++++------------ pagetop/src/base/component/grid/column.rs | 12 ++++---- pagetop/src/base/component/grid/row.rs | 12 ++++---- pagetop/src/base/component/image.rs | 18 +++++++----- 12 files changed, 115 insertions(+), 102 deletions(-) diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 414fb3e4..06b0dd1a 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -32,7 +32,7 @@ impl ModuleTrait for UserModule { } fn form_login() -> ArcComponent { - Form::new() + Form::new()/* .with_id("user-login") .add(form::Input::textfield() .with_name("name") @@ -49,7 +49,7 @@ fn form_login() -> ArcComponent { .with_help_text(l("password_help").as_str()) .arc() ) - .add(form::Button::submit(l("login").as_str()).arc()) + .add(form::Button::submit(l("login").as_str()).arc())*/ .arc() } @@ -57,11 +57,11 @@ async fn login() -> app::Result { Page::new() .with_title( "Identificación del usuario" - ) + )/* .add_to("content", Container::new() .with_id("welcome") .add(form_login()) .arc() - ) + )*/ .render() } diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index a1bf8745..64dd8d7c 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -51,47 +51,49 @@ impl PageComponent for Block { impl Block { pub fn with(html: Markup) -> Self { - Block::new().add(html) + let mut block = Block::new(); + block.add(html); + block } // Block BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_title(mut self, title: &str) -> Self { + pub fn with_title(&mut self, title: &str) -> &Self { self.title.with_value(title); self } - pub fn add(mut self, html: Markup) -> Self { + pub fn add(&mut self, html: Markup) -> &Self { self.html.push(html); self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index dc909a89..7589ea4a 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -36,27 +36,29 @@ impl PageComponent for Chunck { impl Chunck { pub fn with(html: Markup) -> Self { - Chunck::new().add(html) + let mut chunck = Chunck::new(); + chunck.add(html); + chunck } // Chunck BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn add(mut self, html: Markup) -> Self { + pub fn add(&mut self, html: Markup) -> &Self { self.html.push(html); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 2e48ba10..79f9b7a5 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -99,12 +99,12 @@ impl Container { // Container BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } @@ -114,22 +114,22 @@ impl Container { self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index f99f06d3..f6fd474d 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -68,44 +68,48 @@ impl PageComponent for Button { impl Button { pub fn button(value: &str) -> Self { - Button::new().with_value(value) + let mut button = Button::new(); + button.with_value(value); + button } pub fn reset(value: &str) -> Self { - let mut button = Button::new().with_value(value); + let mut button = Button::new(); + button.with_value(value); button.button_type = ButtonType::Reset; button } pub fn submit(value: &str) -> Self { - let mut button = Button::new().with_value(value); + let mut button = Button::new(); + button.with_value(value); button.button_type = ButtonType::Submit; button } // Button BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_name(mut self, name: &str) -> Self { + pub fn with_name(&mut self, name: &str) -> &Self { self.name.with_value(name); self } - pub fn with_value(mut self, value: &str) -> Self { + pub fn with_value(&mut self, value: &str) -> &Self { self.value.with_value(value); self } - pub fn with_autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(&mut self, toggle: bool) -> &Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -113,7 +117,7 @@ impl Button { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(&mut self, toggle: bool) -> &Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -121,17 +125,17 @@ impl Button { self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 40c2f784..bc355a2a 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -95,37 +95,37 @@ impl Date { // Date BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_name(mut self, name: &str) -> Self { + pub fn with_name(&mut self, name: &str) -> &Self { self.name.with_value(name); self } - pub fn with_value(mut self, value: &str) -> Self { + pub fn with_value(&mut self, value: &str) -> &Self { self.value.with_value(value); self } - pub fn with_label(mut self, label: &str) -> Self { + pub fn with_label(&mut self, label: &str) -> &Self { self.label.with_value(label); self } - pub fn with_placeholder(mut self, placeholder: &str) -> Self { + pub fn with_placeholder(&mut self, placeholder: &str) -> &Self { self.placeholder.with_value(placeholder); self } - pub fn with_autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(&mut self, toggle: bool) -> &Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -133,7 +133,7 @@ impl Date { self } - pub fn with_autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(&mut self, toggle: bool) -> &Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -141,7 +141,7 @@ impl Date { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(&mut self, toggle: bool) -> &Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -149,7 +149,7 @@ impl Date { self } - pub fn with_readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(&mut self, toggle: bool) -> &Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -157,7 +157,7 @@ impl Date { self } - pub fn with_required(mut self, toggle: bool) -> Self { + pub fn with_required(&mut self, toggle: bool) -> &Self { self.required.with_value(match toggle { true => "required", false => "", @@ -165,22 +165,22 @@ impl Date { self } - pub fn with_help_text(mut self, help_text: &str) -> Self { + pub fn with_help_text(&mut self, help_text: &str) -> &Self { self.help_text.with_value(help_text); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 9317f9eb..3685d9a1 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -60,27 +60,27 @@ impl Form { // Form BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_action(mut self, action: &str) -> Self { + pub fn with_action(&mut self, action: &str) -> &Self { self.action.with_value(action); self } - pub fn with_charset(mut self, charset: &str) -> Self { + pub fn with_charset(&mut self, charset: &str) -> &Self { self.charset.with_value(charset); self } - pub fn with_method(mut self, method: FormMethod) -> Self { + pub fn with_method(&mut self, method: FormMethod) -> &Self { self.method = method; self } @@ -90,22 +90,22 @@ impl Form { self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index f4734ba0..0e6e56c3 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -32,22 +32,25 @@ impl PageComponent for Hidden { impl Hidden { pub fn set(name: &str, value: &str) -> Self { - Hidden::new().with_name(name).with_value(value) + let mut hidden = Hidden::new(); + hidden.with_name(name); + hidden.with_value(value); + hidden } // Hidden BUILDER. - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_name(mut self, name: &str) -> Self { + pub fn with_name(&mut self, name: &str) -> &Self { self.name.with_value(name); self } - pub fn with_value(mut self, value: &str) -> Self { + pub fn with_value(&mut self, value: &str) -> &Self { self.value.with_value(value); self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 9d6e1afd..c468cdfe 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -149,52 +149,52 @@ impl Input { // Input BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_name(mut self, name: &str) -> Self { + pub fn with_name(&mut self, name: &str) -> &Self { self.name.with_value(name); self } - pub fn with_value(mut self, value: &str) -> Self { + pub fn with_value(&mut self, value: &str) -> &Self { self.value.with_value(value); self } - pub fn with_label(mut self, label: &str) -> Self { + pub fn with_label(&mut self, label: &str) -> &Self { self.label.with_value(label); self } - pub fn with_size(mut self, size: Option) -> Self { + pub fn with_size(&mut self, size: Option) -> &Self { self.size = size; self } - pub fn with_minlength(mut self, minlength: Option) -> Self { + pub fn with_minlength(&mut self, minlength: Option) -> &Self { self.minlength = minlength; self } - pub fn with_maxlength(mut self, maxlength: Option) -> Self { + pub fn with_maxlength(&mut self, maxlength: Option) -> &Self { self.maxlength = maxlength; self } - pub fn with_placeholder(mut self, placeholder: &str) -> Self { + pub fn with_placeholder(&mut self, placeholder: &str) -> &Self { self.placeholder.with_value(placeholder); self } - pub fn with_autofocus(mut self, toggle: bool) -> Self { + pub fn with_autofocus(&mut self, toggle: bool) -> &Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -202,7 +202,7 @@ impl Input { self } - pub fn with_autocomplete(mut self, toggle: bool) -> Self { + pub fn with_autocomplete(&mut self, toggle: bool) -> &Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -210,7 +210,7 @@ impl Input { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn with_disabled(&mut self, toggle: bool) -> &Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -218,7 +218,7 @@ impl Input { self } - pub fn with_readonly(mut self, toggle: bool) -> Self { + pub fn with_readonly(&mut self, toggle: bool) -> &Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -226,7 +226,7 @@ impl Input { self } - pub fn with_required(mut self, toggle: bool) -> Self { + pub fn with_required(&mut self, toggle: bool) -> &Self { self.required.with_value(match toggle { true => "required", false => "", @@ -234,22 +234,22 @@ impl Input { self } - pub fn with_help_text(mut self, help_text: &str) -> Self { + pub fn with_help_text(&mut self, help_text: &str) -> &Self { self.help_text.with_value(help_text); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index a007c83b..e4e5525a 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -46,12 +46,12 @@ impl Column { // Column BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } @@ -61,22 +61,22 @@ impl Column { self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 2a185894..30a5f351 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -46,12 +46,12 @@ impl Row { // Row BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } @@ -61,22 +61,22 @@ impl Row { self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 1384f4df..30cca8f3 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -41,42 +41,44 @@ impl PageComponent for Image { impl Image { pub fn image(source: &str) -> Self { - Image::new().with_source(source) + let mut image = Image::new(); + image.with_source(source); + image } // Image BUILDER. - pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { self.renderable = renderable; self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(&mut self, weight: i8) -> &Self { self.weight = weight; self } - pub fn with_source(mut self, source: &str) -> Self { + pub fn with_source(&mut self, source: &str) -> &Self { self.source.with_value(source); self } - pub fn with_id(mut self, id: &str) -> Self { + pub fn with_id(&mut self, id: &str) -> &Self { self.id.with_value(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { + pub fn set_classes(&mut self, classes: &str) -> &Self { self.classes.set_classes(classes); self } - pub fn add_classes(mut self, classes: &str) -> Self { + pub fn add_classes(&mut self, classes: &str) -> &Self { self.classes.add_classes(classes); self } - pub fn using_template(mut self, template: &str) -> Self { + pub fn using_template(&mut self, template: &str) -> &Self { self.template = template.to_owned(); self } From 93d6d455c8ecc8c37c4ac1c38cd9e859abcbdd0e Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 6 Apr 2022 21:17:56 +0200 Subject: [PATCH 20/80] =?UTF-8?q?Actualiza=20y=20recupera=20definici=C3=B3?= =?UTF-8?q?n=20original=20de=20comp.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prácticamente se revierten los últimos cambios realizados en la estructura de componentes. --- pagetop-admin/src/summary.rs | 7 +-- pagetop-user/src/lib.rs | 14 ++--- pagetop/src/base/component/block.rs | 45 ++++++-------- pagetop/src/base/component/chunck.rs | 25 +++----- pagetop/src/base/component/container.rs | 46 +++++++------- pagetop/src/base/component/form/button.rs | 28 ++++----- pagetop/src/base/component/form/date.rs | 30 ++++----- pagetop/src/base/component/form/form.rs | 76 ++++++++++++----------- pagetop/src/base/component/form/hidden.rs | 13 ++-- pagetop/src/base/component/form/input.rs | 36 +++++------ pagetop/src/base/component/grid/column.rs | 42 +++++++------ pagetop/src/base/component/grid/row.rs | 32 +++++----- pagetop/src/base/component/image.rs | 18 +++--- pagetop/src/base/component/menu.rs | 20 +++--- pagetop/src/base/module/demopage/mod.rs | 28 ++++----- pagetop/src/base/theme/bootsier/mod.rs | 2 +- pagetop/src/response/page/component.rs | 9 --- pagetop/src/response/page/container.rs | 14 +++-- pagetop/src/response/page/mod.rs | 2 +- pagetop/src/response/page/page.rs | 4 +- pagetop/src/theme/definition.rs | 2 +- 21 files changed, 234 insertions(+), 259 deletions(-) diff --git a/pagetop-admin/src/summary.rs b/pagetop-admin/src/summary.rs index 6e6f2158..b91b97fa 100644 --- a/pagetop-admin/src/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -38,18 +38,17 @@ pub async fn summary() -> app::Result { .with_title("Admin") - .add_to("top-menu", top_menu.arc()) + .add_to("top-menu", top_menu) .add_to("content", grid::Row::new() .add_column(grid::Column::new() - .add(side_menu.arc()) + .add(side_menu) ) .add_column(grid::Column::new() .add(Chunck::with(html! { p { "Columna 2"} - }).arc()) + })) ) - .arc() ) diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 06b0dd1a..c40057f0 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -31,8 +31,8 @@ impl ModuleTrait for UserModule { } } -fn form_login() -> ArcComponent { - Form::new()/* +fn form_login() -> Form { + Form::new() .with_id("user-login") .add(form::Input::textfield() .with_name("name") @@ -41,27 +41,23 @@ fn form_login() -> ArcComponent { "app" => SETTINGS.app.name.to_owned() ]).as_str()) .with_autofocus(true) - .arc() ) .add(form::Input::password() .with_name("pass") .with_label(l("password").as_str()) .with_help_text(l("password_help").as_str()) - .arc() ) - .add(form::Button::submit(l("login").as_str()).arc())*/ - .arc() + .add(form::Button::submit(l("login").as_str())) } async fn login() -> app::Result { Page::new() .with_title( "Identificación del usuario" - )/* + ) .add_to("content", Container::new() .with_id("welcome") .add(form_login()) - .arc() - )*/ + ) .render() } diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 64dd8d7c..99950286 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -3,8 +3,8 @@ use crate::prelude::*; pub struct Block { renderable: fn() -> bool, weight : i8, + components: PageContainer, title : OptAttr, - html : Vec, id : OptIden, classes : Classes, template : String, @@ -15,8 +15,8 @@ impl PageComponent for Block { Block { renderable: always, weight : 0, + components: PageContainer::new(), title : OptAttr::none(), - html : Vec::new(), id : OptIden::none(), classes : Classes::none(), template : "default".to_owned(), @@ -40,9 +40,7 @@ impl PageComponent for Block { None => {} } div class="block-body" { - @for html in self.html().iter() { - (*html) - } + (self.components().render(assets)) } } } @@ -50,50 +48,51 @@ impl PageComponent for Block { } impl Block { - pub fn with(html: Markup) -> Self { - let mut block = Block::new(); - block.add(html); - block + + // Block CONTAINER. + + pub fn add(mut self, component: impl PageComponent) -> Self { + self.components.add(component); + self + } + + pub fn components(&self) -> &PageContainer { + &self.components } // Block BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_title(&mut self, title: &str) -> &Self { + pub fn with_title(mut self, title: &str) -> Self { self.title.with_value(title); self } - pub fn add(&mut self, html: Markup) -> &Self { - self.html.push(html); - self - } - - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } @@ -104,10 +103,6 @@ impl Block { self.title.option() } - pub fn html(&self) -> &Vec { - &self.html - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 7589ea4a..0e46c779 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub struct Chunck { renderable: fn() -> bool, weight : i8, - html : Vec, + html : Markup, template : String, } @@ -12,7 +12,7 @@ impl PageComponent for Chunck { Chunck { renderable: always, weight : 0, - html : Vec::new(), + html : html! {}, template : "default".to_owned(), } } @@ -26,46 +26,37 @@ impl PageComponent for Chunck { } fn default_render(&self, _: &mut PageAssets) -> Markup { - html! { - @for html in self.html().iter() { - (*html) - } - } + html! { (*self.html()) } } } impl Chunck { pub fn with(html: Markup) -> Self { let mut chunck = Chunck::new(); - chunck.add(html); + chunck.html = html; chunck } // Chunck BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn add(&mut self, html: Markup) -> &Self { - self.html.push(html); - self - } - - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } // Chunck GETTERS. - pub fn html(&self) -> &Vec { + pub fn html(&self) -> &Markup { &self.html } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 79f9b7a5..70162bb9 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -5,8 +5,8 @@ pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable: fn() -> bool, weight : i8, - container : ContainerType, components: PageContainer, + container : ContainerType, id : OptIden, classes : Classes, template : String, @@ -17,8 +17,8 @@ impl PageComponent for Container { Container { renderable: always, weight : 0, - container : ContainerType::Wrapper, components: PageContainer::new(), + container : ContainerType::Wrapper, id : OptIden::none(), classes : Classes::none(), template : "default".to_owned(), @@ -97,39 +97,45 @@ impl Container { c } - // Container BUILDER. + // Container CONTAINER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { - self.renderable = renderable; - self - } - - pub fn with_weight(&mut self, weight: i8) -> &Self { - self.weight = weight; - self - } - - pub fn add(mut self, component: ArcComponent) -> Self { + pub fn add(mut self, component: impl PageComponent) -> Self { self.components.add(component); self } - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn components(&self) -> &PageContainer { + &self.components + } + + // Container BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } @@ -140,10 +146,6 @@ impl Container { &self.container } - pub fn components(&self) -> &PageContainer { - &self.components - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index f6fd474d..f99f06d3 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -68,48 +68,44 @@ impl PageComponent for Button { impl Button { pub fn button(value: &str) -> Self { - let mut button = Button::new(); - button.with_value(value); - button + Button::new().with_value(value) } pub fn reset(value: &str) -> Self { - let mut button = Button::new(); - button.with_value(value); + let mut button = Button::new().with_value(value); button.button_type = ButtonType::Reset; button } pub fn submit(value: &str) -> Self { - let mut button = Button::new(); - button.with_value(value); + let mut button = Button::new().with_value(value); button.button_type = ButtonType::Submit; button } // Button BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_name(&mut self, name: &str) -> &Self { + pub fn with_name(mut self, name: &str) -> Self { self.name.with_value(name); self } - pub fn with_value(&mut self, value: &str) -> &Self { + pub fn with_value(mut self, value: &str) -> Self { self.value.with_value(value); self } - pub fn with_autofocus(&mut self, toggle: bool) -> &Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -117,7 +113,7 @@ impl Button { self } - pub fn with_disabled(&mut self, toggle: bool) -> &Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -125,17 +121,17 @@ impl Button { self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index bc355a2a..40c2f784 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -95,37 +95,37 @@ impl Date { // Date BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_name(&mut self, name: &str) -> &Self { + pub fn with_name(mut self, name: &str) -> Self { self.name.with_value(name); self } - pub fn with_value(&mut self, value: &str) -> &Self { + pub fn with_value(mut self, value: &str) -> Self { self.value.with_value(value); self } - pub fn with_label(&mut self, label: &str) -> &Self { + pub fn with_label(mut self, label: &str) -> Self { self.label.with_value(label); self } - pub fn with_placeholder(&mut self, placeholder: &str) -> &Self { + pub fn with_placeholder(mut self, placeholder: &str) -> Self { self.placeholder.with_value(placeholder); self } - pub fn with_autofocus(&mut self, toggle: bool) -> &Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -133,7 +133,7 @@ impl Date { self } - pub fn with_autocomplete(&mut self, toggle: bool) -> &Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -141,7 +141,7 @@ impl Date { self } - pub fn with_disabled(&mut self, toggle: bool) -> &Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -149,7 +149,7 @@ impl Date { self } - pub fn with_readonly(&mut self, toggle: bool) -> &Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -157,7 +157,7 @@ impl Date { self } - pub fn with_required(&mut self, toggle: bool) -> &Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -165,22 +165,22 @@ impl Date { self } - pub fn with_help_text(&mut self, help_text: &str) -> &Self { + pub fn with_help_text(mut self, help_text: &str) -> Self { self.help_text.with_value(help_text); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 3685d9a1..07cb6e17 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -5,10 +5,10 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : i8, + elements : PageContainer, action : OptAttr, charset : OptAttr, method : FormMethod, - elements : PageContainer, id : OptIden, classes : Classes, template : String, @@ -19,10 +19,10 @@ impl PageComponent for Form { Form { renderable: always, weight : 0, + elements : PageContainer::new(), action : OptAttr::none(), charset : OptAttr::some("UTF-8"), method : FormMethod::Post, - elements : PageContainer::new(), id : OptIden::none(), classes : Classes::none(), template : "default".to_owned(), @@ -58,54 +58,60 @@ impl PageComponent for Form { impl Form { - // Form BUILDER. + // Form CONTAINER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { - self.renderable = renderable; - self - } - - pub fn with_weight(&mut self, weight: i8) -> &Self { - self.weight = weight; - self - } - - pub fn with_action(&mut self, action: &str) -> &Self { - self.action.with_value(action); - self - } - - pub fn with_charset(&mut self, charset: &str) -> &Self { - self.charset.with_value(charset); - self - } - - pub fn with_method(&mut self, method: FormMethod) -> &Self { - self.method = method; - self - } - - pub fn add(mut self, element: ArcComponent) -> Self { + pub fn add(mut self, element: impl PageComponent) -> Self { self.elements.add(element); self } - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn elements(&self) -> &PageContainer { + &self.elements + } + + // Form BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn with_action(mut self, action: &str) -> Self { + self.action.with_value(action); + self + } + + pub fn with_charset(mut self, charset: &str) -> Self { + self.charset.with_value(charset); + self + } + + pub fn with_method(mut self, method: FormMethod) -> Self { + self.method = method; + self + } + + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } @@ -124,10 +130,6 @@ impl Form { &self.method } - pub fn elements(&self) -> &PageContainer { - &self.elements - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 0e6e56c3..8f2cc4b3 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -32,25 +32,24 @@ impl PageComponent for Hidden { impl Hidden { pub fn set(name: &str, value: &str) -> Self { - let mut hidden = Hidden::new(); - hidden.with_name(name); - hidden.with_value(value); - hidden + Hidden::new() + .with_name(name) + .with_value(value) } // Hidden BUILDER. - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_name(&mut self, name: &str) -> &Self { + pub fn with_name(mut self, name: &str) -> Self { self.name.with_value(name); self } - pub fn with_value(&mut self, value: &str) -> &Self { + pub fn with_value(mut self, value: &str) -> Self { self.value.with_value(value); self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index c468cdfe..9d6e1afd 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -149,52 +149,52 @@ impl Input { // Input BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_name(&mut self, name: &str) -> &Self { + pub fn with_name(mut self, name: &str) -> Self { self.name.with_value(name); self } - pub fn with_value(&mut self, value: &str) -> &Self { + pub fn with_value(mut self, value: &str) -> Self { self.value.with_value(value); self } - pub fn with_label(&mut self, label: &str) -> &Self { + pub fn with_label(mut self, label: &str) -> Self { self.label.with_value(label); self } - pub fn with_size(&mut self, size: Option) -> &Self { + pub fn with_size(mut self, size: Option) -> Self { self.size = size; self } - pub fn with_minlength(&mut self, minlength: Option) -> &Self { + pub fn with_minlength(mut self, minlength: Option) -> Self { self.minlength = minlength; self } - pub fn with_maxlength(&mut self, maxlength: Option) -> &Self { + pub fn with_maxlength(mut self, maxlength: Option) -> Self { self.maxlength = maxlength; self } - pub fn with_placeholder(&mut self, placeholder: &str) -> &Self { + pub fn with_placeholder(mut self, placeholder: &str) -> Self { self.placeholder.with_value(placeholder); self } - pub fn with_autofocus(&mut self, toggle: bool) -> &Self { + pub fn with_autofocus(mut self, toggle: bool) -> Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -202,7 +202,7 @@ impl Input { self } - pub fn with_autocomplete(&mut self, toggle: bool) -> &Self { + pub fn with_autocomplete(mut self, toggle: bool) -> Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -210,7 +210,7 @@ impl Input { self } - pub fn with_disabled(&mut self, toggle: bool) -> &Self { + pub fn with_disabled(mut self, toggle: bool) -> Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -218,7 +218,7 @@ impl Input { self } - pub fn with_readonly(&mut self, toggle: bool) -> &Self { + pub fn with_readonly(mut self, toggle: bool) -> Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -226,7 +226,7 @@ impl Input { self } - pub fn with_required(&mut self, toggle: bool) -> &Self { + pub fn with_required(mut self, toggle: bool) -> Self { self.required.with_value(match toggle { true => "required", false => "", @@ -234,22 +234,22 @@ impl Input { self } - pub fn with_help_text(&mut self, help_text: &str) -> &Self { + pub fn with_help_text(mut self, help_text: &str) -> Self { self.help_text.with_value(help_text); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index e4e5525a..f29544ca 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -44,49 +44,51 @@ impl PageComponent for Column { impl Column { - // Column BUILDER. + // Column CONTAINER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { - self.renderable = renderable; - self - } - - pub fn with_weight(&mut self, weight: i8) -> &Self { - self.weight = weight; - self - } - - pub fn add(mut self, component: ArcComponent) -> Self { + pub fn add(mut self, component: impl PageComponent) -> Self { self.components.add(component); self } - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn components(&self) -> &PageContainer { + &self.components + } + + // Column BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.renderable = renderable; + self + } + + pub fn with_weight(mut self, weight: i8) -> Self { + self.weight = weight; + self + } + + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } // Column GETTERS. - pub fn components(&self) -> &PageContainer { - &self.components - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 30a5f351..59645b79 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -44,49 +44,51 @@ impl PageComponent for Row { impl Row { + // Row CONTAINER. + + pub fn add_column(mut self, column: grid::Column) -> Self { + self.columns.add(column); + self + } + + pub fn columns(&self) -> &PageContainer { + &self.columns + } + // Row BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn add_column(mut self, column: grid::Column) -> Self { - self.columns.add(column.arc()); - self - } - - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } // Row GETTERS. - pub fn columns(&self) -> &PageContainer { - &self.columns - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 30cca8f3..1384f4df 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -41,44 +41,42 @@ impl PageComponent for Image { impl Image { pub fn image(source: &str) -> Self { - let mut image = Image::new(); - image.with_source(source); - image + Image::new().with_source(source) } // Image BUILDER. - pub fn with_renderable(&mut self, renderable: fn() -> bool) -> &Self { + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { self.renderable = renderable; self } - pub fn with_weight(&mut self, weight: i8) -> &Self { + pub fn with_weight(mut self, weight: i8) -> Self { self.weight = weight; self } - pub fn with_source(&mut self, source: &str) -> &Self { + pub fn with_source(mut self, source: &str) -> Self { self.source.with_value(source); self } - pub fn with_id(&mut self, id: &str) -> &Self { + pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self } - pub fn set_classes(&mut self, classes: &str) -> &Self { + pub fn set_classes(mut self, classes: &str) -> Self { self.classes.set_classes(classes); self } - pub fn add_classes(&mut self, classes: &str) -> &Self { + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self } - pub fn using_template(&mut self, template: &str) -> &Self { + pub fn using_template(mut self, template: &str) -> Self { self.template = template.to_owned(); self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 3f2b4ff4..01a60129 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -209,6 +209,17 @@ impl PageComponent for Menu { impl Menu { + // Menu CONTAINER. + + pub fn add(mut self, item: MenuItem) -> Self { + self.items.add(item); + self + } + + pub fn items(&self) -> &PageContainer { + &self.items + } + // Menu BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { @@ -221,11 +232,6 @@ impl Menu { self } - pub fn add(mut self, item: MenuItem) -> Self { - self.items.add(item.arc()); - self - } - pub fn with_id(mut self, id: &str) -> Self { self.id.with_value(id); self @@ -248,10 +254,6 @@ impl Menu { // Menu GETTERS. - pub fn items(&self) -> &PageContainer { - &self.items - } - pub fn id(&self) -> &Option { self.id.option() } diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index d71c7176..489b6d3b 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -35,7 +35,7 @@ async fn demo() -> app::Result { .render() } -fn hello_world() -> ArcComponent { +fn hello_world() -> Container { Container::header() .add(grid::Row::new() .add_column(grid::Column::new() @@ -68,17 +68,15 @@ fn hello_world() -> ArcComponent { i class="fas fa-paper-plane" {} "Get quote" } - }).arc()) + })) ) .add_column(grid::Column::new() - .add(Image::image("/bootsier/images/demo-header.svg").arc()) + .add(Image::image("/bootsier/images/demo-header.svg")) ) - .arc() ) - .arc() } -fn hello_world_original() -> ArcComponent { +fn hello_world_original() -> Chunck { Chunck::with(html! { header id="header" class="header" { div class="container" { @@ -123,10 +121,10 @@ fn hello_world_original() -> ArcComponent { } } } - }).arc() + }) } -fn just_visiting() -> ArcComponent { +fn just_visiting() -> Chunck { Chunck::with(html! { div id="details" class="basic-1" { div class="container" { @@ -153,10 +151,10 @@ fn just_visiting() -> ArcComponent { } } } - }).arc() + }) } -fn about_pagetop() -> ArcComponent { +fn about_pagetop() -> Chunck { Chunck::with(html! { div id="pagetop" class="basic-2" { div class="container" { @@ -177,10 +175,10 @@ fn about_pagetop() -> ArcComponent { } } } - }).arc() + }) } -fn promo_pagetop() -> ArcComponent { +fn promo_pagetop() -> Chunck { Chunck::with(html! { div id="promo" class="basic-3" { div class="container" { @@ -202,10 +200,10 @@ fn promo_pagetop() -> ArcComponent { } } } - }).arc() + }) } -fn reporting_problems() -> ArcComponent { +fn reporting_problems() -> Chunck { Chunck::with(html! { div id="reporting" class="basic-4" { div class="container" { @@ -225,5 +223,5 @@ fn reporting_problems() -> ArcComponent { } } } - }).arc() + }) } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index b169351d..90111723 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -77,7 +77,7 @@ impl ThemeTrait for BootsierTheme { } } } - }).arc()) + })) .render() } } diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index b9a920d3..630b8a9b 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -3,11 +3,8 @@ use crate::response::page::PageAssets; use downcast_rs::{Downcast, impl_downcast}; -use std::sync::Arc; use std::any::type_name; -pub type ArcComponent = Arc; - pub trait PageComponent: Downcast + Send + Sync { fn new() -> Self where Self: Sized; @@ -36,12 +33,6 @@ pub trait PageComponent: Downcast + Send + Sync { 0 } - #[allow(unused_mut)] - fn arc(mut self) -> ArcComponent where Self: Sized { - let component = self; - Arc::new(component) - } - #[allow(unused_variables)] fn default_render(&self, assets: &mut PageAssets) -> Markup { html! {} diff --git a/pagetop/src/response/page/container.rs b/pagetop/src/response/page/container.rs index 7e5d4953..011e5f50 100644 --- a/pagetop/src/response/page/container.rs +++ b/pagetop/src/response/page/container.rs @@ -1,22 +1,24 @@ use crate::html::{Markup, html}; -use crate::response::page::{ArcComponent, PageAssets, render_component}; +use crate::response::page::{PageAssets, PageComponent, render_component}; + +use std::sync::Arc; #[derive(Clone)] -pub struct PageContainer(Vec); +pub struct PageContainer(Vec>); impl PageContainer { pub fn new() -> Self { PageContainer(Vec::new()) } - pub fn new_with(component: ArcComponent) -> Self { + pub fn new_with(component: impl PageComponent) -> Self { let mut container = PageContainer::new(); container.add(component); container } - pub fn add(&mut self, component: ArcComponent) { - self.0.push(component); + pub fn add(&mut self, component: impl PageComponent) { + self.0.push(Arc::new(component)); } pub fn render(&self, assets: &mut PageAssets) -> Markup { @@ -28,4 +30,4 @@ impl PageContainer { } } } -} \ No newline at end of file +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 63c19a47..f34070e2 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -7,7 +7,7 @@ pub use assets::{ }; mod component; -pub use component::{ArcComponent, PageComponent}; +pub use component::PageComponent; mod container; pub use container::PageContainer; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 5cbe80cb..5501678a 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -100,7 +100,7 @@ impl<'a> Page<'a> { pub fn add_to( &mut self, region: &'a str, - component: ArcComponent + component: impl PageComponent ) -> &mut Self { if let Some(regions) = self.regions.get_mut(region) { regions.add(component); @@ -205,7 +205,7 @@ pub fn render_component( } } -pub fn add_component_to(region: &'static str, component: ArcComponent) { +pub fn add_component_to(region: &'static str, component: impl PageComponent) { let mut hmap = COMPONENTS.write().unwrap(); if let Some(regions) = hmap.get_mut(region) { regions.add(component); diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index db4c0e37..acc30f47 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -104,7 +104,7 @@ pub trait ThemeTrait: Send + Sync { div { h1 { (s) } } - }).arc()) + })) .render() } } From e11b36f7edb97c1fcc355b111884ebc2e819362e Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 6 Apr 2022 23:54:38 +0200 Subject: [PATCH 21/80] Mejora el uso de referencias en los componentes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sin embargo requiere duplicar todos los métodos para recibir una referencia mutable a self en uno y directamente self en otro. --- pagetop/src/base/component/grid/row.rs | 5 +++++ pagetop/src/base/theme/bulmix/mod.rs | 8 ++++++-- pagetop/src/response/page/container.rs | 10 +++++----- pagetop/src/response/page/page.rs | 2 +- pagetop/src/theme/definition.rs | 2 +- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 59645b79..96d74afc 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -77,6 +77,11 @@ impl Row { self } + pub fn set_classes_ref(&mut self, classes: &str) -> &Self { + self.classes.set_classes(classes); + self + } + pub fn add_classes(mut self, classes: &str) -> Self { self.classes.add_classes(classes); self diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 284353c1..cf83a8f6 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -34,17 +34,21 @@ impl ThemeTrait for BulmixTheme { fn render_component( &self, - component: &dyn PageComponent, + component: &mut dyn PageComponent, assets: &mut PageAssets ) -> Option { match component.name() { "GridRow" => { - let row = component.downcast_ref::().unwrap(); + let row = component.downcast_mut::().unwrap(); + row.set_classes_ref("Prueba"); + None + /* Some(html! { div id=[row.id()] class=[row.classes("columns")] { (row.columns().render(assets)) } }) + */ }, "GridColumn" => { let col = component.downcast_ref::().unwrap(); diff --git a/pagetop/src/response/page/container.rs b/pagetop/src/response/page/container.rs index 011e5f50..2e052ee9 100644 --- a/pagetop/src/response/page/container.rs +++ b/pagetop/src/response/page/container.rs @@ -1,10 +1,10 @@ use crate::html::{Markup, html}; use crate::response::page::{PageAssets, PageComponent, render_component}; -use std::sync::Arc; +use std::sync::{Arc, RwLock}; #[derive(Clone)] -pub struct PageContainer(Vec>); +pub struct PageContainer(Vec>>); impl PageContainer { pub fn new() -> Self { @@ -18,15 +18,15 @@ impl PageContainer { } pub fn add(&mut self, component: impl PageComponent) { - self.0.push(Arc::new(component)); + self.0.push(Arc::new(RwLock::new(component))); } pub fn render(&self, assets: &mut PageAssets) -> Markup { let mut components = self.0.clone(); - components.sort_by_key(|c| c.weight()); + components.sort_by_key(|c| c.read().unwrap().weight()); html! { @for c in components.iter() { - (render_component(&**c, assets)) + (render_component(&mut *c.write().unwrap(), assets)) } } } diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 5501678a..56db5ecc 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -193,7 +193,7 @@ impl<'a> Page<'a> { } pub fn render_component( - component: &dyn PageComponent, + component: &mut dyn PageComponent, assets: &mut PageAssets ) -> Markup { match component.is_renderable() { diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index acc30f47..457860c7 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -77,7 +77,7 @@ pub trait ThemeTrait: Send + Sync { #[allow(unused_variables)] fn render_component( &self, - component: &dyn PageComponent, + component: &mut dyn PageComponent, assets: &mut PageAssets ) -> Option { None From ba4cc982befeb57d844fe28e954687b50826beba Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 9 Apr 2022 18:40:44 +0200 Subject: [PATCH 22/80] =?UTF-8?q?A=C3=B1ade=20alteraci=C3=B3n=20de=20compo?= =?UTF-8?q?nentes=20antes=20del=20render?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Los componentes implementan a la vez el paradigma "builder" y la modificación por "setters" para poder ser modificados durante la creación de la página o alterados antes de ser renderizados. --- pagetop/src/base/component/block.rs | 67 ++++--- pagetop/src/base/component/chunck.rs | 41 +++-- pagetop/src/base/component/container.rs | 114 +++++++----- pagetop/src/base/component/form/button.rs | 102 +++++++---- pagetop/src/base/component/form/date.rs | 152 +++++++++++----- pagetop/src/base/component/form/form.rs | 83 ++++++--- pagetop/src/base/component/form/hidden.rs | 29 ++- pagetop/src/base/component/form/input.rs | 209 +++++++++++++++------- pagetop/src/base/component/grid/column.rs | 58 +++--- pagetop/src/base/component/grid/row.rs | 63 ++++--- pagetop/src/base/component/image.rs | 67 ++++--- pagetop/src/base/component/menu.rs | 86 ++++++--- pagetop/src/base/theme/bulmix/mod.rs | 26 +-- pagetop/src/html/classes.rs | 83 +++++++-- pagetop/src/html/mod.rs | 2 +- pagetop/src/html/optattr.rs | 10 +- pagetop/src/html/optiden.rs | 12 +- pagetop/src/response/page/assets.rs | 2 +- pagetop/src/response/page/component.rs | 4 + pagetop/src/response/page/mod.rs | 3 + pagetop/src/response/page/page.rs | 44 +++-- pagetop/src/theme/definition.rs | 27 ++- 22 files changed, 872 insertions(+), 412 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 99950286..86370ff4 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -13,12 +13,12 @@ pub struct Block { impl PageComponent for Block { fn new() -> Self { Block { - renderable: always, + renderable: render_always, weight : 0, components: PageContainer::new(), - title : OptAttr::none(), - id : OptIden::none(), - classes : Classes::none(), + title : OptAttr::new(), + id : OptIden::new(), + classes : Classes::new_with_default("block"), template : "default".to_owned(), } } @@ -34,7 +34,7 @@ impl PageComponent for Block { fn default_render(&self, assets: &mut PageAssets) -> Markup { let id = assets.serial_id(self.name(), self.id()); html! { - div id=(id) class=[self.classes("block")] { + div id=(id) class=[self.classes()] { @match self.title() { Some(title) => h2 class="block-title" { (title) }, None => {} @@ -63,36 +63,63 @@ impl Block { // Block BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_title(mut self, title: &str) -> Self { - self.title.with_value(title); + self.alter_title(title); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Block ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_title(&mut self, title: &str) -> &mut Self { + self.title.with_value(title); + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -107,15 +134,11 @@ impl Block { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 0e46c779..6dbc0ff1 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -10,7 +10,7 @@ pub struct Chunck { impl PageComponent for Chunck { fn new() -> Self { Chunck { - renderable: always, + renderable: render_always, weight : 0, html : html! {}, template : "default".to_owned(), @@ -32,24 +32,49 @@ impl PageComponent for Chunck { impl Chunck { pub fn with(html: Markup) -> Self { - let mut chunck = Chunck::new(); - chunck.html = html; - chunck + Chunck::new().with_html(html) } // Chunck BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); + self + } + + pub fn with_html(mut self, html: Markup) -> Self { + self.alter_html(html); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Chunck ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_html(&mut self, html: Markup) -> &mut Self { + self.html = html; + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -64,7 +89,3 @@ impl Chunck { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 70162bb9..fab8225a 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -3,25 +3,27 @@ use crate::prelude::*; pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { - renderable: fn() -> bool, - weight : i8, - components: PageContainer, - container : ContainerType, - id : OptIden, - classes : Classes, - template : String, + renderable : fn() -> bool, + weight : i8, + components : PageContainer, + container : ContainerType, + id : OptIden, + classes : Classes, + inner_classes: Classes, + template : String, } impl PageComponent for Container { fn new() -> Self { Container { - renderable: always, - weight : 0, - components: PageContainer::new(), - container : ContainerType::Wrapper, - id : OptIden::none(), - classes : Classes::none(), - template : "default".to_owned(), + renderable : render_always, + weight : 0, + components : PageContainer::new(), + container : ContainerType::Wrapper, + id : OptIden::new(), + classes : Classes::new_with_default("container"), + inner_classes: Classes::new_with_default("container"), + template : "default".to_owned(), } } @@ -36,35 +38,35 @@ impl PageComponent for Container { fn default_render(&self, assets: &mut PageAssets) -> Markup { match self.container_type() { ContainerType::Header => html! { - header id=[self.id()] class=[self.classes("header")] { - div class="container" { + header id=[self.id()] class=[self.classes()] { + div class=[self.inner_classes()] { (self.components().render(assets)) } } }, ContainerType::Footer => html! { - footer id=[self.id()] class=[self.classes("footer")] { - div class="container" { + footer id=[self.id()] class=[self.classes()] { + div class=[self.inner_classes()] { (self.components().render(assets)) } } }, ContainerType::Main => html! { - main id=[self.id()] class=[self.classes("main")] { - div class="container" { + main id=[self.id()] class=[self.classes()] { + div class=[self.inner_classes()] { (self.components().render(assets)) } } }, ContainerType::Section => html! { - section id=[self.id()] class=[self.classes("section")] { - div class="container" { + section id=[self.id()] class=[self.classes()] { + div class=[self.inner_classes()] { (self.components().render(assets)) } } }, _ => html! { - div id=[self.id()] class=[self.classes("container")] { + div id=[self.id()] class=[self.classes()] { (self.components().render(assets)) } } @@ -74,25 +76,25 @@ impl PageComponent for Container { impl Container { pub fn header() -> Self { - let mut c = Container::new(); + let mut c = Container::new().with_classes("header", ClassesOp::SetDefault); c.container = ContainerType::Header; c } pub fn footer() -> Self { - let mut c = Container::new(); + let mut c = Container::new().with_classes("footer", ClassesOp::SetDefault); c.container = ContainerType::Footer; c } pub fn main() -> Self { - let mut c = Container::new(); + let mut c = Container::new().with_classes("main", ClassesOp::SetDefault); c.container = ContainerType::Main; c } pub fn section() -> Self { - let mut c = Container::new(); + let mut c = Container::new().with_classes("section", ClassesOp::SetDefault); c.container = ContainerType::Section; c } @@ -111,31 +113,63 @@ impl Container { // Container BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_inner_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_inner_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Container ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_inner_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.inner_classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -150,15 +184,15 @@ impl Container { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() + } + + pub fn inner_classes(&self) -> &Option { + self.inner_classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index f99f06d3..4c75dc62 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -17,16 +17,17 @@ pub struct Button { impl PageComponent for Button { fn new() -> Self { Button { - renderable : always, + renderable : render_always, weight : 0, button_type: ButtonType::Button, - name : OptAttr::none(), - value : OptAttr::none(), - autofocus : OptAttr::none(), - disabled : OptAttr::none(), - classes : Classes::none(), + name : OptAttr::new(), + value : OptAttr::new(), + autofocus : OptAttr::new(), + disabled : OptAttr::new(), + classes : Classes::new_with_default("btn btn-primary"), template : "default".to_owned(), } + .with_classes("form-button", ClassesOp::AddFirst) } fn is_renderable(&self) -> bool { @@ -38,10 +39,10 @@ impl PageComponent for Button { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (button_type, button_class) = match self.button_type() { - ButtonType::Button => ("button", "btn btn-primary form-button"), - ButtonType::Reset => ("reset", "btn btn-primary form-reset" ), - ButtonType::Submit => ("submit", "btn btn-primary form-submit"), + let button_type = match self.button_type() { + ButtonType::Button => "button", + ButtonType::Reset => "reset", + ButtonType::Submit => "submit", }; let id = match self.name() { Some(name) => Some(concat_string!("edit-", name)), @@ -51,7 +52,7 @@ impl PageComponent for Button { button type=(button_type) id=[id] - class=[self.classes(button_class)] + class=[self.classes()] name=[self.name()] value=[self.value()] autofocus=[self.autofocus()] @@ -72,13 +73,17 @@ impl Button { } pub fn reset(value: &str) -> Self { - let mut button = Button::new().with_value(value); + let mut button = Button::new() + .with_classes("form-reset", ClassesOp::Replace("form-button")) + .with_value(value); button.button_type = ButtonType::Reset; button } pub fn submit(value: &str) -> Self { - let mut button = Button::new().with_value(value); + let mut button = Button::new() + .with_classes("form-submit", ClassesOp::Replace("form-button")) + .with_value(value); button.button_type = ButtonType::Submit; button } @@ -86,26 +91,68 @@ impl Button { // Button BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_name(mut self, name: &str) -> Self { - self.name.with_value(name); + self.alter_name(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value.with_value(value); + self.alter_value(value); self } pub fn with_autofocus(mut self, toggle: bool) -> Self { + self.alter_autofocus(toggle); + self + } + + pub fn with_disabled(mut self, toggle: bool) -> Self { + self.alter_disabled(toggle); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Button ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_name(&mut self, name: &str) -> &mut Self { + self.name.with_value(name); + self + } + + pub fn alter_value(&mut self, value: &str) -> &mut Self { + self.value.with_value(value); + self + } + + pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -113,7 +160,7 @@ impl Button { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -121,17 +168,12 @@ impl Button { self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); self } - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); - self - } - - pub fn using_template(mut self, template: &str) -> Self { + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -158,15 +200,11 @@ impl Button { self.disabled.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 40c2f784..10e795cb 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -20,21 +20,22 @@ pub struct Date { impl PageComponent for Date { fn new() -> Self { Date { - renderable : always, + renderable : render_always, weight : 0, - name : OptAttr::none(), - value : OptAttr::none(), - label : OptAttr::none(), - placeholder : OptAttr::none(), - autofocus : OptAttr::none(), - autocomplete: OptAttr::none(), - disabled : OptAttr::none(), - readonly : OptAttr::none(), - required : OptAttr::none(), - help_text : OptAttr::none(), - classes : Classes::none(), + name : OptAttr::new(), + value : OptAttr::new(), + label : OptAttr::new(), + placeholder : OptAttr::new(), + autofocus : OptAttr::new(), + autocomplete: OptAttr::new(), + disabled : OptAttr::new(), + readonly : OptAttr::new(), + required : OptAttr::new(), + help_text : OptAttr::new(), + classes : Classes::new_with_default("form-item"), template : "default".to_owned(), } + .with_classes("form-type-date", ClassesOp::AddFirst) } fn is_renderable(&self) -> bool { @@ -46,18 +47,12 @@ impl PageComponent for Date { } fn default_render(&self, _: &mut PageAssets) -> Markup { - let (classes, id) = match self.name() { - Some(name) => ( - concat_string!("form-item form-item-", name, " form-type-date"), - Some(concat_string!("edit-", name)) - ), - None => ( - "form-item form-type-date".to_owned(), - None - ) + let id = match self.name() { + Some(name) => Some(concat_string!("edit-", name)), + None => None, }; html! { - div class=[self.classes(classes.as_str())] { + div class=[self.classes()] { @match self.label() { Some(label) => label class="form-label" for=[&id] { (label) " " @@ -96,36 +91,108 @@ impl Date { // Date BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_name(mut self, name: &str) -> Self { - self.name.with_value(name); + self.alter_name(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value.with_value(value); + self.alter_value(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label.with_value(label); + self.alter_label(label); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder.with_value(placeholder); + self.alter_placeholder(placeholder); self } pub fn with_autofocus(mut self, toggle: bool) -> Self { + self.alter_autofocus(toggle); + self + } + + pub fn with_autocomplete(mut self, toggle: bool) -> Self { + self.alter_autocomplete(toggle); + self + } + + pub fn with_disabled(mut self, toggle: bool) -> Self { + self.alter_disabled(toggle); + self + } + + pub fn with_readonly(mut self, toggle: bool) -> Self { + self.alter_readonly(toggle); + self + } + + pub fn with_required(mut self, toggle: bool) -> Self { + self.alter_required(toggle); + self + } + + pub fn with_help_text(mut self, help_text: &str) -> Self { + self.alter_help_text(help_text); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Date ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_name(&mut self, name: &str) -> &mut Self { + self.name.with_value(name); + self + } + + pub fn alter_value(&mut self, value: &str) -> &mut Self { + self.value.with_value(value); + self + } + + pub fn alter_label(&mut self, label: &str) -> &mut Self { + self.label.with_value(label); + self + } + + pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self { + self.placeholder.with_value(placeholder); + self + } + + pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -133,7 +200,7 @@ impl Date { self } - pub fn with_autocomplete(mut self, toggle: bool) -> Self { + pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -141,7 +208,7 @@ impl Date { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -149,7 +216,7 @@ impl Date { self } - pub fn with_readonly(mut self, toggle: bool) -> Self { + pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -157,7 +224,7 @@ impl Date { self } - pub fn with_required(mut self, toggle: bool) -> Self { + pub fn alter_required(&mut self, toggle: bool) -> &mut Self { self.required.with_value(match toggle { true => "required", false => "", @@ -165,22 +232,17 @@ impl Date { self } - pub fn with_help_text(mut self, help_text: &str) -> Self { + pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self { self.help_text.with_value(help_text); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); self } - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); - self - } - - pub fn using_template(mut self, template: &str) -> Self { + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -227,15 +289,11 @@ impl Date { self.help_text.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 07cb6e17..73581ca2 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -17,14 +17,14 @@ pub struct Form { impl PageComponent for Form { fn new() -> Self { Form { - renderable: always, + renderable: render_always, weight : 0, elements : PageContainer::new(), - action : OptAttr::none(), - charset : OptAttr::some("UTF-8"), + action : OptAttr::new(), + charset : OptAttr::new_with_value("UTF-8"), method : FormMethod::Post, - id : OptIden::none(), - classes : Classes::none(), + id : OptIden::new(), + classes : Classes::new_with_default("form"), template : "default".to_owned(), } } @@ -45,7 +45,7 @@ impl PageComponent for Form { html! { form id=[self.id()] - class=[self.classes("form")] + class=[self.classes()] action=[self.action()] method=[method] accept-charset=[self.charset()] @@ -72,46 +72,83 @@ impl Form { // Form BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_action(mut self, action: &str) -> Self { - self.action.with_value(action); + self.alter_action(action); self } pub fn with_charset(mut self, charset: &str) -> Self { - self.charset.with_value(charset); + self.alter_charset(charset); self } pub fn with_method(mut self, method: FormMethod) -> Self { - self.method = method; + self.alter_method(method); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Form ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_action(&mut self, action: &str) -> &mut Self { + self.action.with_value(action); + self + } + + pub fn alter_charset(&mut self, charset: &str) -> &mut Self { + self.charset.with_value(charset); + self + } + + pub fn alter_method(&mut self, method: FormMethod) -> &mut Self { + self.method = method; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -134,15 +171,11 @@ impl Form { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 8f2cc4b3..736aa4ce 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -10,8 +10,8 @@ impl PageComponent for Hidden { fn new() -> Self { Hidden { weight: 0, - name : OptIden::none(), - value : OptAttr::none(), + name : OptIden::new(), + value : OptAttr::new(), } } @@ -32,24 +32,39 @@ impl PageComponent for Hidden { impl Hidden { pub fn set(name: &str, value: &str) -> Self { - Hidden::new() - .with_name(name) - .with_value(value) + Hidden::new().with_name(name).with_value(value) } // Hidden BUILDER. pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_name(mut self, name: &str) -> Self { - self.name.with_value(name); + self.alter_name(name); self } pub fn with_value(mut self, value: &str) -> Self { + self.alter_value(value); + self + } + + // Hidden ALTER. + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_name(&mut self, name: &str) -> &mut Self { + self.name.with_value(name); + self + } + + pub fn alter_value(&mut self, value: &str) -> &mut Self { self.value.with_value(value); self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 9d6e1afd..71d801b7 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -26,25 +26,26 @@ pub struct Input { impl PageComponent for Input { fn new() -> Self { Input { - renderable : always, + renderable : render_always, weight : 0, input_type : InputType::Textfield, - name : OptIden::none(), - value : OptAttr::none(), - label : OptAttr::none(), + name : OptIden::new(), + value : OptAttr::new(), + label : OptAttr::new(), size : Some(60), minlength : None, maxlength : Some(128), - placeholder : OptAttr::none(), - autofocus : OptAttr::none(), - autocomplete: OptAttr::none(), - disabled : OptAttr::none(), - readonly : OptAttr::none(), - required : OptAttr::none(), - help_text : OptAttr::none(), - classes : Classes::none(), + placeholder : OptAttr::new(), + autofocus : OptAttr::new(), + autocomplete: OptAttr::new(), + disabled : OptAttr::new(), + readonly : OptAttr::new(), + required : OptAttr::new(), + help_text : OptAttr::new(), + classes : Classes::new_with_default("form-item"), template : "default".to_owned(), } + .with_classes("form-type-textfield", ClassesOp::AddFirst) } fn is_renderable(&self) -> bool { @@ -55,27 +56,28 @@ impl PageComponent for Input { self.weight } + fn before_render(&mut self, _: &mut PageAssets) { + if let Some(name) = self.name() { + let class = concat_string!("form-item-", name); + self.alter_classes(class.as_str(), ClassesOp::AddFirst); + } + } + fn default_render(&self, _: &mut PageAssets) -> Markup { - let (type_input, type_class) = match self.input_type() { - InputType::Email => ("email", "form-type-email"), - InputType::Password => ("password", "form-type-password"), - InputType::Search => ("search", "form-type-search"), - InputType::Telephone => ("tel", "form-type-telephone"), - InputType::Textfield => ("text", "form-type-textfield"), - InputType::Url => ("url", "form-type-url") + let type_input = match self.input_type() { + InputType::Email => "email", + InputType::Password => "password", + InputType::Search => "search", + InputType::Telephone => "tel", + InputType::Textfield => "text", + InputType::Url => "url", }; - let (class, id) = match self.name() { - Some(name) => ( - concat_string!("form-item form-item-", name, " ", type_class), - Some(concat_string!("edit-", name)) - ), - None => ( - concat_string!("form-item ", type_class), - None - ) + let id = match self.name() { + Some(name) => Some(concat_string!("edit-", name)), + None => None, }; html! { - div class=(class) { + div class=[self.classes()] { @match self.label() { Some(label) => label class="form-label" for=[&id] { (label) " " @@ -118,31 +120,36 @@ impl Input { } pub fn password() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-password", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Password; input } pub fn search() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-search", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Search; input } pub fn email() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-email", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Email; input } pub fn telephone() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-telephone", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Telephone; input } pub fn url() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-url", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Url; input } @@ -150,51 +157,138 @@ impl Input { // Input BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_name(mut self, name: &str) -> Self { - self.name.with_value(name); + self.alter_name(name); self } pub fn with_value(mut self, value: &str) -> Self { - self.value.with_value(value); + self.alter_value(value); self } pub fn with_label(mut self, label: &str) -> Self { - self.label.with_value(label); + self.alter_label(label); self } pub fn with_size(mut self, size: Option) -> Self { - self.size = size; + self.alter_size(size); self } pub fn with_minlength(mut self, minlength: Option) -> Self { - self.minlength = minlength; + self.alter_minlength(minlength); self } pub fn with_maxlength(mut self, maxlength: Option) -> Self { - self.maxlength = maxlength; + self.alter_maxlength(maxlength); self } pub fn with_placeholder(mut self, placeholder: &str) -> Self { - self.placeholder.with_value(placeholder); + self.alter_placeholder(placeholder); self } pub fn with_autofocus(mut self, toggle: bool) -> Self { + self.alter_autofocus(toggle); + self + } + + pub fn with_autocomplete(mut self, toggle: bool) -> Self { + self.alter_autocomplete(toggle); + self + } + + pub fn with_disabled(mut self, toggle: bool) -> Self { + self.alter_disabled(toggle); + self + } + + pub fn with_readonly(mut self, toggle: bool) -> Self { + self.alter_readonly(toggle); + self + } + + pub fn with_required(mut self, toggle: bool) -> Self { + self.alter_required(toggle); + self + } + + pub fn with_help_text(mut self, help_text: &str) -> Self { + self.alter_help_text(help_text); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Input ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_name(&mut self, name: &str) -> &mut Self { + self.name.with_value(name); + self + } + + pub fn alter_value(&mut self, value: &str) -> &mut Self { + self.value.with_value(value); + self + } + + pub fn alter_label(&mut self, label: &str) -> &mut Self { + self.label.with_value(label); + self + } + + pub fn alter_size(&mut self, size: Option) -> &mut Self { + self.size = size; + self + } + + pub fn alter_minlength(&mut self, minlength: Option) -> &mut Self { + self.minlength = minlength; + self + } + + pub fn alter_maxlength(&mut self, maxlength: Option) -> &mut Self { + self.maxlength = maxlength; + self + } + + pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self { + self.placeholder.with_value(placeholder); + self + } + + pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self { self.autofocus.with_value(match toggle { true => "autofocus", false => "", @@ -202,7 +296,7 @@ impl Input { self } - pub fn with_autocomplete(mut self, toggle: bool) -> Self { + pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self { self.autocomplete.with_value(match toggle { true => "", false => "off", @@ -210,7 +304,7 @@ impl Input { self } - pub fn with_disabled(mut self, toggle: bool) -> Self { + pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self { self.disabled.with_value(match toggle { true => "disabled", false => "", @@ -218,7 +312,7 @@ impl Input { self } - pub fn with_readonly(mut self, toggle: bool) -> Self { + pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self { self.readonly.with_value(match toggle { true => "readonly", false => "", @@ -226,7 +320,7 @@ impl Input { self } - pub fn with_required(mut self, toggle: bool) -> Self { + pub fn alter_required(&mut self, toggle: bool) -> &mut Self { self.required.with_value(match toggle { true => "required", false => "", @@ -234,22 +328,17 @@ impl Input { self } - pub fn with_help_text(mut self, help_text: &str) -> Self { + pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self { self.help_text.with_value(help_text); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); self } - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); - self - } - - pub fn using_template(mut self, template: &str) -> Self { + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -312,15 +401,11 @@ impl Input { self.help_text.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index f29544ca..77512ea2 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -12,11 +12,11 @@ pub struct Column { impl PageComponent for Column { fn new() -> Self { Column { - renderable: always, + renderable: render_always, weight : 0, components: PageContainer::new(), - id : OptIden::none(), - classes : Classes::none(), + id : OptIden::new(), + classes : Classes::new_with_default("col"), template : "default".to_owned(), } } @@ -35,7 +35,7 @@ impl PageComponent for Column { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[self.id()] class=[self.classes("col")] { + div id=[self.id()] class=[self.classes()] { (self.components().render(assets)) } } @@ -58,31 +58,53 @@ impl Column { // Column BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Column ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -93,15 +115,11 @@ impl Column { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 96d74afc..4574b090 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -12,11 +12,11 @@ pub struct Row { impl PageComponent for Row { fn new() -> Self { Row { - renderable: always, + renderable: render_always, weight : 0, columns : PageContainer::new(), - id : OptIden::none(), - classes : Classes::none(), + id : OptIden::new(), + classes : Classes::new_with_default("row"), template : "default".to_owned(), } } @@ -35,7 +35,7 @@ impl PageComponent for Row { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! { - div id=[self.id()] class=[self.classes("row")] { + div id=[self.id()] class=[self.classes()] { (self.columns().render(assets)) } } @@ -58,36 +58,53 @@ impl Row { // Row BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn set_classes_ref(&mut self, classes: &str) -> &Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Row ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -98,15 +115,11 @@ impl Row { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 1384f4df..62690679 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -12,11 +12,11 @@ pub struct Image { impl PageComponent for Image { fn new() -> Self { Image { - renderable: always, + renderable: render_always, weight : 0, - source : OptAttr::none(), - id : OptIden::none(), - classes : Classes::none(), + source : OptAttr::new(), + id : OptIden::new(), + classes : Classes::new_with_default("img-fluid"), template : "default".to_owned(), } } @@ -34,7 +34,7 @@ impl PageComponent for Image { img src=[self.source()] id=[self.id()] - class=[self.classes("img-fluid")]; + class=[self.classes()]; } } } @@ -47,36 +47,63 @@ impl Image { // Image BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_source(mut self, source: &str) -> Self { - self.source.with_value(source); + self.alter_source(source); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Image ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_source(&mut self, source: &str) -> &mut Self { + self.source.with_value(source); + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -91,15 +118,11 @@ impl Image { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 01a60129..68c5c97e 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -23,7 +23,7 @@ pub struct MenuItem { impl PageComponent for MenuItem { fn new() -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Void, } @@ -72,7 +72,7 @@ impl PageComponent for MenuItem { impl MenuItem { pub fn label(label: &str) -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Label(label.to_owned()), } @@ -80,7 +80,7 @@ impl MenuItem { pub fn link(label: &str, path: &str) -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Link( label.to_owned(), @@ -91,7 +91,7 @@ impl MenuItem { pub fn link_blank(label: &str, path: &str) -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::LinkBlank( label.to_owned(), @@ -102,7 +102,7 @@ impl MenuItem { pub fn html(html: Markup) -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Html(html), } @@ -110,7 +110,7 @@ impl MenuItem { pub fn separator() -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Separator, } @@ -118,7 +118,7 @@ impl MenuItem { pub fn submenu(label: &str, menu: Menu) -> Self { MenuItem { - renderable: always, + renderable: render_always, weight : 0, item_type : MenuItemType::Submenu( label.to_owned(), @@ -130,11 +130,23 @@ impl MenuItem { // MenuItem BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { + self.alter_weight(weight); + self + } + + // MenuItem ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { self.weight = weight; self } @@ -162,11 +174,11 @@ pub struct Menu { impl PageComponent for Menu { fn new() -> Self { Menu { - renderable: always, + renderable: render_always, weight : 0, items : PageContainer::new(), - id : OptIden::none(), - classes : Classes::none(), + id : OptIden::new(), + classes : Classes::new_with_default("sm sm-clean"), template : "default".to_owned(), } } @@ -194,7 +206,7 @@ impl PageComponent for Menu { let id = assets.serial_id(self.name(), self.id()); html! { - ul id=(id) class=[self.classes("sm sm-clean")] { + ul id=(id) class=[self.classes()] { (self.items().render(assets)) } script type="text/javascript" defer { @@ -223,31 +235,53 @@ impl Menu { // Menu BUILDER. pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { - self.renderable = renderable; + self.alter_renderable(renderable); self } pub fn with_weight(mut self, weight: i8) -> Self { - self.weight = weight; + self.alter_weight(weight); self } pub fn with_id(mut self, id: &str) -> Self { - self.id.with_value(id); + self.alter_id(id); self } - pub fn set_classes(mut self, classes: &str) -> Self { - self.classes.set_classes(classes); - self - } - - pub fn add_classes(mut self, classes: &str) -> Self { - self.classes.add_classes(classes); + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); self } pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Menu ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { self.template = template.to_owned(); self } @@ -258,15 +292,11 @@ impl Menu { self.id.option() } - pub fn classes(&self, default: &str) -> Option { - self.classes.option(default) + pub fn classes(&self) -> &Option { + self.classes.option() } pub fn template(&self) -> &str { self.template.as_str() } } - -fn always() -> bool { - true -} diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index cf83a8f6..c7aa3cb2 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -32,33 +32,21 @@ impl ThemeTrait for BulmixTheme { .add_jquery(); } - fn render_component( + fn before_render_component( &self, component: &mut dyn PageComponent, - assets: &mut PageAssets - ) -> Option { + _assets: &mut PageAssets + ) { match component.name() { "GridRow" => { let row = component.downcast_mut::().unwrap(); - row.set_classes_ref("Prueba"); - None - /* - Some(html! { - div id=[row.id()] class=[row.classes("columns")] { - (row.columns().render(assets)) - } - }) - */ + row.alter_classes("columns", ClassesOp::SetDefault); }, "GridColumn" => { - let col = component.downcast_ref::().unwrap(); - Some(html! { - div id=[col.id()] class=[col.classes("column")] { - (col.components().render(assets)) - } - }) + let col = component.downcast_mut::().unwrap(); + col.alter_classes("column", ClassesOp::SetDefault); }, - _ => None + _ => {}, } } } diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index 6c41aafb..225d6537 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -1,23 +1,82 @@ use crate::concat_string; -pub struct Classes(String); +pub enum ClassesOp { + Add, + AddAfter(&'static str), + AddBefore(&'static str), + AddFirst, + Replace(&'static str), + Reset, + SetDefault, +} + +pub struct Classes { + default: String, + added : String, + option : Option, +} impl Classes { - pub fn none() -> Self { - Classes("".to_owned()) + pub fn new() -> Self { + Classes { + default: "".to_owned(), + added : "".to_owned(), + option : None, + } } - pub fn set_classes(&mut self, classes: &str) -> &mut Self { - self.0 = classes.to_owned(); + pub fn new_with_default(default: &str) -> Self { + let mut classes = Self::new(); + classes.alter(default, ClassesOp::SetDefault); + classes + } + + pub fn alter(&mut self, classes: &str, op: ClassesOp) -> &Self { + let classes = classes.trim(); + match op { + ClassesOp::Add => self.added.push_str(concat_string!(" ", classes).as_str()), + + ClassesOp::AddAfter(class) => { + let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); + match v_added.iter().position(|c| c.eq(&class)) { + Some(pos) => v_added.insert(pos + 1, classes), + _ => v_added.push(classes), + } + self.added = v_added.join(" "); + }, + + ClassesOp::AddBefore(class) => { + let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); + match v_added.iter().position(|c| c.eq(&class)) { + Some(pos) => v_added.insert(pos, classes), + _ => v_added.insert(0, classes), + } + self.added = v_added.join(" "); + }, + + ClassesOp::AddFirst => self.added = concat_string!(classes, " ", self.added), + + ClassesOp::Replace(class) => { + let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); + match v_added.iter().position(|c| c.eq(&class)) { + Some(pos) => { + v_added.remove(pos); + v_added.insert(pos, classes); + }, + _ => v_added.push(classes), + } + self.added = v_added.join(" "); + }, + + ClassesOp::Reset => self.added = classes.to_owned(), + + ClassesOp::SetDefault => self.default = classes.to_owned(), + } + self.option = Some(concat_string!(self.default, " ", self.added).trim().to_owned()); self } - pub fn add_classes(&mut self, classes: &str) -> &mut Self { - self.0 = concat_string!(self.0, " ", classes).trim().to_owned(); - self - } - - pub fn option(&self, default: &str) -> Option { - Some(concat_string!(default.to_owned(), " ", self.0).trim().to_owned()) + pub fn option(&self) -> &Option { + &self.option } } diff --git a/pagetop/src/html/mod.rs b/pagetop/src/html/mod.rs index 52f735fe..56e5c6d2 100644 --- a/pagetop/src/html/mod.rs +++ b/pagetop/src/html/mod.rs @@ -5,4 +5,4 @@ pub use optiden::OptIden; mod optattr; pub use optattr::OptAttr; mod classes; -pub use classes::Classes; +pub use classes::{Classes, ClassesOp}; diff --git a/pagetop/src/html/optattr.rs b/pagetop/src/html/optattr.rs index d009e32e..86c21e8c 100644 --- a/pagetop/src/html/optattr.rs +++ b/pagetop/src/html/optattr.rs @@ -1,14 +1,14 @@ pub struct OptAttr(Option); impl OptAttr { - pub fn none() -> Self { + pub fn new() -> Self { OptAttr(None) } - pub fn some(value: &str) -> Self { - let mut o = OptAttr(None); - o.with_value(value); - o + pub fn new_with_value(value: &str) -> Self { + let mut option = Self::new(); + option.with_value(value); + option } pub fn with_value(&mut self, value: &str) -> &mut Self { diff --git a/pagetop/src/html/optiden.rs b/pagetop/src/html/optiden.rs index 52a65c10..450867d9 100644 --- a/pagetop/src/html/optiden.rs +++ b/pagetop/src/html/optiden.rs @@ -1,17 +1,17 @@ pub struct OptIden(Option); impl OptIden { - pub fn none() -> Self { + pub fn new() -> Self { OptIden(None) } - pub fn some(id: &str) -> Self { - let mut o = OptIden(None); - o.with_value(id); - o + pub fn new_with_value(id: &str) -> Self { + let mut option = Self::new(); + option.with_value(id); + option } - pub fn with_value(&mut self, id: &str) -> &mut Self { + pub fn with_value(&mut self, id: &str) -> &Self { let id = id.trim(); self.0 = match id.is_empty() { true => None, diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index 3d42a06f..8ab4d2eb 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -257,7 +257,7 @@ impl PageAssets { /// Assets GETTERS. - pub fn theme(&mut self) -> &'static dyn ThemeTrait { + pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait { self.theme } diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 630b8a9b..05528fc8 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -33,6 +33,10 @@ pub trait PageComponent: Downcast + Send + Sync { 0 } + #[allow(unused_variables)] + fn before_render(&mut self, assets: &mut PageAssets) { + } + #[allow(unused_variables)] fn default_render(&self, assets: &mut PageAssets) -> Markup { html! {} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index f34070e2..527f74f9 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -17,3 +17,6 @@ pub use page::Page; pub use page::render_component; pub use page::add_component_to; +pub fn render_always() -> bool { true } + +pub fn render_never() -> bool { false } \ No newline at end of file diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 56db5ecc..f7bee609 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,6 +1,6 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; -use crate::html::{Classes, DOCTYPE, Markup, OptAttr, html}; +use crate::html::*; use crate::response::page::*; use std::sync::RwLock; @@ -55,18 +55,18 @@ impl<'a> Page<'a> { pub fn new() -> Self { Page { language : match &*DEFAULT_LANGUAGE { - Some(language) => OptAttr::some(language), - _ => OptAttr::none(), + Some(language) => OptAttr::new_with_value(language), + _ => OptAttr::new(), }, direction : match &*DEFAULT_DIRECTION { - Some(direction) => OptAttr::some(direction), - _ => OptAttr::none(), + Some(direction) => OptAttr::new_with_value(direction), + _ => OptAttr::new(), }, - title : OptAttr::none(), - description : OptAttr::none(), + title : OptAttr::new(), + description : OptAttr::new(), assets : PageAssets::new(), regions : COMPONENTS.read().unwrap().clone(), - body_classes: Classes::none(), + body_classes: Classes::new_with_default("body"), template : "default".to_owned(), } } @@ -110,13 +110,8 @@ impl<'a> Page<'a> { self } - pub fn set_body_classes(&mut self, classes: &str) -> &mut Self { - self.body_classes.set_classes(classes); - self - } - - pub fn add_body_classes(&mut self, classes: &str) -> &mut Self { - self.body_classes.add_classes(classes); + pub fn alter_body_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.body_classes.alter(classes, op); self } @@ -147,8 +142,8 @@ impl<'a> Page<'a> { &mut self.assets } - pub fn body_classes(&self, default: &str) -> Option { - self.body_classes.option(default) + pub fn body_classes(&self) -> &Option { + self.body_classes.option() } pub fn template(&self) -> &str { @@ -192,14 +187,15 @@ impl<'a> Page<'a> { } } -pub fn render_component( - component: &mut dyn PageComponent, - assets: &mut PageAssets -) -> Markup { +pub fn render_component(component: &mut dyn PageComponent, assets: &mut PageAssets) -> Markup { + component.before_render(assets); + assets.theme().before_render_component(component, assets); match component.is_renderable() { - true => match assets.theme().render_component(component, assets) { - Some(html) => html, - None => component.default_render(assets) + true => { + match assets.theme().render_component(component, assets) { + Some(html) => html, + None => component.default_render(assets) + } }, false => html! {} } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 457860c7..983bf0a6 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -55,7 +55,7 @@ pub trait ThemeTrait: Send + Sync { fn render_page_body(&self, page: &mut Page) -> Markup { html! { - body class=[page.body_classes("body")] { + body class=[page.body_classes()] { @match page.template() { "admin" => { @for region in &["top-menu", "side-menu", "content"] { @@ -75,10 +75,29 @@ pub trait ThemeTrait: Send + Sync { } #[allow(unused_variables)] - fn render_component( + fn before_render_component( &self, component: &mut dyn PageComponent, assets: &mut PageAssets + ) { + /* + Cómo usarlo: + + match component.name() { + "Block" => { + let block = component.downcast_mut::().unwrap(); + block.alter_title("New title"); + }, + _ => {}, + } + */ + } + + #[allow(unused_variables)] + fn render_component( + &self, + component: &dyn PageComponent, + assets: &mut PageAssets ) -> Option { None /* @@ -89,10 +108,10 @@ pub trait ThemeTrait: Send + Sync { let block = component.downcast_ref::().unwrap(); match block.template() { "default" => Some(block_default(block)), - _ => None + _ => None, } }, - _ => None + _ => None, } */ } From 993d6fc0eb0fd31ba09cb457961ac477a31b18f1 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 9 Apr 2022 20:54:01 +0200 Subject: [PATCH 23/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-user/Cargo.toml | 2 +- pagetop/Cargo.toml | 12 ++++++------ pagetop/STARTER.bin.Cargo.toml | 2 +- pagetop/STARTER.lib.Cargo.toml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pagetop-user/Cargo.toml b/pagetop-user/Cargo.toml index 59c24cb3..d5e3aa84 100644 --- a/pagetop-user/Cargo.toml +++ b/pagetop-user/Cargo.toml @@ -14,5 +14,5 @@ repository = "https://gitlab.com/manuelcillero/pagetop" [dependencies] pagetop = { path = "../pagetop" } -sea-orm = { version = "0.6.0" } +sea-orm = { version = "0.7.1" } serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 8598de96..b058c7b4 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.6" +version = "0.0.8" edition = "2021" authors = [ @@ -35,12 +35,12 @@ url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } tracing = "0.1.32" -tracing-appender = "0.2.1" -tracing-subscriber = { version = "0.3.9", features = ["json", "env-filter"] } +tracing-appender = "0.2.2" +tracing-subscriber = { version = "0.3.10", features = ["json", "env-filter"] } tracing-unwrap = { version = "0.9.2", default-features = false } tracing-actix-web = "0.2" -fluent-templates = "0.6.1" +fluent-templates = "0.7.1" unic-langid = "0.9.0" actix-web = "3.3.3" @@ -53,13 +53,13 @@ sycamore = { version = "0.7.1", features = ["ssr"] } serde = { version = "1.0", features = ["derive"] } [dependencies.sea-orm] -version = "0.6.0" +version = "0.7.1" features = ["debug-print", "macros", "runtime-async-std-native-tls"] default-features = false optional = true [dependencies.sea-schema] -version = "0.6.0" +version = "0.7.1" features = ["debug-print", "migration"] default-features = false optional = true diff --git a/pagetop/STARTER.bin.Cargo.toml b/pagetop/STARTER.bin.Cargo.toml index 9c6c8979..f9c6560f 100644 --- a/pagetop/STARTER.bin.Cargo.toml +++ b/pagetop/STARTER.bin.Cargo.toml @@ -22,6 +22,6 @@ actix-web = "3.3.3" # Si se usa la macro html!: maud = { version = "0.23.0" } # Si se usa base de datos: -sea-orm = { version = "0.6.0" } +sea-orm = { version = "0.7.1" } # Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/STARTER.lib.Cargo.toml b/pagetop/STARTER.lib.Cargo.toml index e98fed13..7a74f96e 100644 --- a/pagetop/STARTER.lib.Cargo.toml +++ b/pagetop/STARTER.lib.Cargo.toml @@ -11,6 +11,6 @@ pagetop = { path = "../pagetop" } # Si se usa la macro html!: maud = { version = "0.23.0" } # Si se usa base de datos: -sea-orm = { version = "0.6.0" } +sea-orm = { version = "0.7.1" } # Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } From d37b2e09abc8797ccfa5baed0d06ca06cbecb01a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 19 Apr 2022 01:32:42 +0200 Subject: [PATCH 24/80] =?UTF-8?q?A=C3=B1ade=20nueva=20macro=20module=5Fnam?= =?UTF-8?q?e!()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devuelve el nombre del módulo actual en el que se ejecuta la macro. --- pagetop/src/db.rs | 1 + pagetop/src/prelude.rs | 1 + pagetop/src/util.rs | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/pagetop/src/db.rs b/pagetop/src/db.rs index d68a5aac..550f8f66 100644 --- a/pagetop/src/db.rs +++ b/pagetop/src/db.rs @@ -11,6 +11,7 @@ pub mod entity { pub mod migration { pub use sea_schema::migration::prelude::*; + pub use crate::module_name; } #[macro_export] diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 429c9449..55c9681e 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -4,6 +4,7 @@ pub use crate::{ args, concat_string, + module_name, theme_static_files, }; diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index c2fd58d3..02bb584e 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -18,6 +18,17 @@ macro_rules! args { }}; } +#[macro_export] +macro_rules! module_name { + () => {{ + let name = module_path!(); + match name.rfind("::") { + Some(position) => &name[(position + 2)..], + None => name + } + }}; +} + #[macro_export] macro_rules! theme_static_files { ( $cfg:ident, $dir:expr ) => {{ From 4af658600366768a3d734dbc1c7fd32c842e83c6 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 19 Apr 2022 01:47:33 +0200 Subject: [PATCH 25/80] =?UTF-8?q?A=C3=B1ade=20la=20creaci=C3=B3n=20de=20ta?= =?UTF-8?q?blas=20asociadas=20a=20usuarios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-user/src/lib.rs | 5 +- .../m20220312_000001_create_table_role.rs | 65 +++++++++++++ .../m20220312_000001_create_table_user.rs | 54 ----------- ...312_000002_create_table_role_permission.rs | 77 +++++++++++++++ .../m20220312_000003_create_table_user.rs | 97 +++++++++++++++++++ ...m20220312_000004_create_table_user_role.rs | 80 +++++++++++++++ pagetop-user/src/migration/mod.rs | 5 +- 7 files changed, 327 insertions(+), 56 deletions(-) create mode 100644 pagetop-user/src/migration/m20220312_000001_create_table_role.rs delete mode 100644 pagetop-user/src/migration/m20220312_000001_create_table_user.rs create mode 100644 pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs create mode 100644 pagetop-user/src/migration/m20220312_000003_create_table_user.rs create mode 100644 pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index c40057f0..4059cc79 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -26,7 +26,10 @@ impl ModuleTrait for UserModule { fn migrations(&self) -> Vec> { vec![ - boxed_migration!(m20220312_000001_create_table_user) + boxed_migration!(m20220312_000001_create_table_role), + boxed_migration!(m20220312_000002_create_table_role_permission), + boxed_migration!(m20220312_000003_create_table_user), + boxed_migration!(m20220312_000004_create_table_user_role), ] } } diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs new file mode 100644 index 00000000..af453f74 --- /dev/null +++ b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs @@ -0,0 +1,65 @@ +use pagetop::db::migration::*; + +#[derive(Iden)] +enum Role { Table, + Rid, + Name, + Weight, +} + +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + // Store user roles. + Table::create() + .table(Role::Table) + .if_not_exists() + // Primary Key: Unique role ID. + .col(ColumnDef::new(Role::Rid) + .unsigned() + .not_null() + .auto_increment() + .primary_key() + ) + // Unique role name. + .col(ColumnDef::new(Role::Name) + .string_len(64) + .not_null() + .unique_key() + ) + // The weight of this role in listings and the user interface. + .col(ColumnDef::new(Role::Weight) + .integer() + .not_null() + .default(0) + ) + // INDEXES. + .index(Index::create() + .name("name-weight") + .col(Role::Name) + .col(Role::Weight) + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(Role::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() + } +} diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_user.rs b/pagetop-user/src/migration/m20220312_000001_create_table_user.rs deleted file mode 100644 index 729b72e0..00000000 --- a/pagetop-user/src/migration/m20220312_000001_create_table_user.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::db::migration::*; - -#[derive(Iden)] -enum User { - Table, - Id, - Title, - Text, -} - -pub struct Migration; - -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20220312_000001_create_table_user" - } -} - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(User::Table) - .if_not_exists() - .col(ColumnDef::new(User::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(User::Title) - .string() - .not_null() - ) - .col(ColumnDef::new(User::Text) - .string() - .not_null() - ) - .to_owned() - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(User::Table) - .to_owned() - ) - .await - } -} diff --git a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs new file mode 100644 index 00000000..0148af5f --- /dev/null +++ b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs @@ -0,0 +1,77 @@ +use pagetop::db::migration::*; + +#[derive(Iden)] +enum RolePermission { Table, + Rid, + Permission, + Module, +} +#[derive(Iden)] +enum Role { Table, + Rid, +// ... +} + +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + // Stores the permissions assigned to user roles. + Table::create() + .table(RolePermission::Table) + .if_not_exists() + // Foreign Key: Role::Rid. + .col(ColumnDef::new(RolePermission::Rid) + .unsigned() + .not_null() + ) + // A single permission granted to the role identified by Rid. + .col(ColumnDef::new(RolePermission::Permission) + .string_len(128) + .not_null() + ) + // The module declaring the permission. + .col(ColumnDef::new(RolePermission::Module) + .string_len(255) + .not_null() + ) + // INDEXES. + .primary_key(Index::create() + .col(RolePermission::Rid) + .col(RolePermission::Permission) + ) + .index(Index::create() + .name("permission") + .col(RolePermission::Permission) + ) + .foreign_key( + ForeignKey::create() + .name("fk_role_permission-rid") + .from(RolePermission::Table, RolePermission::Rid) + .to(Role::Table, Role::Rid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(RolePermission::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() + } +} diff --git a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs new file mode 100644 index 00000000..bf151f50 --- /dev/null +++ b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs @@ -0,0 +1,97 @@ +use pagetop::db::migration::*; + +#[derive(Iden)] +enum User { Table, + Uid, + Name, + Pass, + Mail, + Created, + Changed, + Access, + Login, + Status, + Timezone, +} + +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + // Stores user data. + Table::create() + .table(User::Table) + .if_not_exists() + // Primary Key: Unique user ID. + .col(ColumnDef::new(User::Uid) + .unsigned() + .not_null() + .primary_key() + ) + // Unique user name. + .col(ColumnDef::new(User::Name) + .string_len(60) + .not_null() + .unique_key() + ) + // User's password (hashed). + .col(ColumnDef::new(User::Pass) + .string_len(128) + .not_null() + ) + // User's e-mail address. + .col(ColumnDef::new(User::Mail) + .string_len(255) + ) + // Timestamp for when user was created. + .col(ColumnDef::new(User::Created) + .timestamp() + .not_null() + ) + // Timestamp for when user was changed. + .col(ColumnDef::new(User::Changed) + .timestamp() + .not_null() + ) + // Timestamp for previous time user accessed the site. + .col(ColumnDef::new(User::Access) + .timestamp() + .not_null() + ) + // Timestamp for user's last login. + .col(ColumnDef::new(User::Login) + .timestamp() + .not_null() + ) + // Whether the user is active(1) or blocked(0). + .col(ColumnDef::new(User::Status) + .boolean() + .not_null() + ) + // User's time zone. + .col(ColumnDef::new(User::Timezone) + .string_len(32) + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(User::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() + } +} diff --git a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs new file mode 100644 index 00000000..f92d019b --- /dev/null +++ b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs @@ -0,0 +1,80 @@ +use pagetop::db::migration::*; + +#[derive(Iden)] +enum UserRole { Table, + Uid, + Rid, +} +#[derive(Iden)] +enum User { Table, + Uid, +// ... +} +#[derive(Iden)] +enum Role { Table, + Rid, +// ... +} + +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + // Maps users to roles. + Table::create() + .table(UserRole::Table) + .if_not_exists() + // Foreign Key: User::Uid for user. + .col(ColumnDef::new(UserRole::Uid) + .unsigned() + .not_null() + ) + // Foreign Key: Role::Rid for role. + .col(ColumnDef::new(UserRole::Rid) + .unsigned() + .not_null() + ) + // INDEXES. + .primary_key(Index::create() + .col(UserRole::Uid) + .col(UserRole::Rid) + ) + .foreign_key( + ForeignKey::create() + .name("fk_user_role-uid") + .from(UserRole::Table, UserRole::Uid) + .to(User::Table, User::Uid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .foreign_key( + ForeignKey::create() + .name("fk_user_role-rid") + .from(UserRole::Table, UserRole::Rid) + .to(Role::Table, Role::Rid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .to_owned() + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop() + .table(UserRole::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() + } +} diff --git a/pagetop-user/src/migration/mod.rs b/pagetop-user/src/migration/mod.rs index 60836980..f56a9b53 100644 --- a/pagetop-user/src/migration/mod.rs +++ b/pagetop-user/src/migration/mod.rs @@ -1 +1,4 @@ -pub mod m20220312_000001_create_table_user; +pub mod m20220312_000001_create_table_role; +pub mod m20220312_000002_create_table_role_permission; +pub mod m20220312_000003_create_table_user; +pub mod m20220312_000004_create_table_user_role; From d07611d044c701d3560d427c455b24ad766190f5 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 20 Apr 2022 00:21:49 +0200 Subject: [PATCH 26/80] =?UTF-8?q?A=C3=B1ade=20las=20entidades=20asociadas?= =?UTF-8?q?=20a=20roles=20y=20usuarios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-user/src/entity/mod.rs | 3 ++ pagetop-user/src/entity/role.rs | 41 ++++++++++++++++++++ pagetop-user/src/entity/role_permission.rs | 35 +++++++++++++++++ pagetop-user/src/entity/user.rs | 43 +++++++++++++++------ pagetop-user/src/entity/user_role.rs | 45 ++++++++++++++++++++++ 5 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 pagetop-user/src/entity/role.rs create mode 100644 pagetop-user/src/entity/role_permission.rs create mode 100644 pagetop-user/src/entity/user_role.rs diff --git a/pagetop-user/src/entity/mod.rs b/pagetop-user/src/entity/mod.rs index 22d12a38..a8287bfe 100644 --- a/pagetop-user/src/entity/mod.rs +++ b/pagetop-user/src/entity/mod.rs @@ -1 +1,4 @@ +pub mod role; +pub mod role_permission; pub mod user; +pub mod user_role; diff --git a/pagetop-user/src/entity/role.rs b/pagetop-user/src/entity/role.rs new file mode 100644 index 00000000..2520ebe8 --- /dev/null +++ b/pagetop-user/src/entity/role.rs @@ -0,0 +1,41 @@ +use pagetop::db::entity::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "role")] +pub struct Model { + #[sea_orm(primary_key)] + pub rid : u32, + #[sea_orm(unique)] + pub name : String, + #[sea_orm(default_value = 0)] + pub weight: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + RolePermission, + UserRole, +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::RolePermission => Entity::has_many(super::role_permission::Entity).into(), + Self::UserRole => Entity::has_many(super::user_role::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::RolePermission.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserRole.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/role_permission.rs b/pagetop-user/src/entity/role_permission.rs new file mode 100644 index 00000000..2c2859d1 --- /dev/null +++ b/pagetop-user/src/entity/role_permission.rs @@ -0,0 +1,35 @@ +use pagetop::db::entity::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "role_permission")] +pub struct Model { + #[sea_orm(primary_key)] + pub rid : u32, + #[sea_orm(primary_key)] + pub permission: String, + pub module : String, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Role, +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Role => Entity::belongs_to(super::role::Entity) + .from(Column::Rid) + .to(super::role::Column::Rid) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Role.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/user.rs b/pagetop-user/src/entity/user.rs index d0db4a98..8bec2f1e 100644 --- a/pagetop-user/src/entity/user.rs +++ b/pagetop-user/src/entity/user.rs @@ -1,18 +1,39 @@ -use crate::db::entity::*; -use serde::{Deserialize, Serialize}; +use pagetop::db::entity::*; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] #[sea_orm(table_name = "user")] pub struct Model { - #[sea_orm(primary_key)] - #[serde(skip_deserializing)] - pub id: i32, - pub title: String, - #[sea_orm(column_type = "Text")] - pub text: String, + #[sea_orm(primary_key, auto_increment = false)] + pub uid : u32, + #[sea_orm(unique)] + pub name : String, + pub pass : String, + pub mail : Option, + pub created : DateTimeUtc, + pub changed : DateTimeUtc, + pub access : DateTimeUtc, + pub login : DateTimeUtc, + pub status : bool, + pub timezone: Option, } -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + UserRole, +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::UserRole => Entity::has_many(super::user_role::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserRole.def() + } +} impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/user_role.rs b/pagetop-user/src/entity/user_role.rs new file mode 100644 index 00000000..23a6af8f --- /dev/null +++ b/pagetop-user/src/entity/user_role.rs @@ -0,0 +1,45 @@ +use pagetop::db::entity::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "user_role")] +pub struct Model { + #[sea_orm(primary_key)] + pub uid: u32, + #[sea_orm(primary_key)] + pub rid: u32, +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + User, + Role, +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::User => Entity::belongs_to(super::user::Entity) + .from(Column::Uid) + .to(super::user::Column::Uid) + .into(), + Self::Role => Entity::belongs_to(super::role::Entity) + .from(Column::Rid) + .to(super::role::Column::Rid) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Role.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} From 13c2e7768866715eae379521a743dacaa6cebfc8 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 22 Apr 2022 20:54:44 +0200 Subject: [PATCH 27/80] Elimina la excesiva rigidez que impone SeaORM --- pagetop-user/Cargo.toml | 1 - pagetop-user/src/entity/mod.rs | 4 -- pagetop-user/src/entity/role.rs | 41 -------------------- pagetop-user/src/entity/role_permission.rs | 35 ----------------- pagetop-user/src/entity/user.rs | 39 ------------------- pagetop-user/src/entity/user_role.rs | 45 ---------------------- pagetop-user/src/lib.rs | 1 - 7 files changed, 166 deletions(-) delete mode 100644 pagetop-user/src/entity/mod.rs delete mode 100644 pagetop-user/src/entity/role.rs delete mode 100644 pagetop-user/src/entity/role_permission.rs delete mode 100644 pagetop-user/src/entity/user.rs delete mode 100644 pagetop-user/src/entity/user_role.rs diff --git a/pagetop-user/Cargo.toml b/pagetop-user/Cargo.toml index d5e3aa84..3395241f 100644 --- a/pagetop-user/Cargo.toml +++ b/pagetop-user/Cargo.toml @@ -14,5 +14,4 @@ repository = "https://gitlab.com/manuelcillero/pagetop" [dependencies] pagetop = { path = "../pagetop" } -sea-orm = { version = "0.7.1" } serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop-user/src/entity/mod.rs b/pagetop-user/src/entity/mod.rs deleted file mode 100644 index a8287bfe..00000000 --- a/pagetop-user/src/entity/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod role; -pub mod role_permission; -pub mod user; -pub mod user_role; diff --git a/pagetop-user/src/entity/role.rs b/pagetop-user/src/entity/role.rs deleted file mode 100644 index 2520ebe8..00000000 --- a/pagetop-user/src/entity/role.rs +++ /dev/null @@ -1,41 +0,0 @@ -use pagetop::db::entity::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "role")] -pub struct Model { - #[sea_orm(primary_key)] - pub rid : u32, - #[sea_orm(unique)] - pub name : String, - #[sea_orm(default_value = 0)] - pub weight: i32, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - RolePermission, - UserRole, -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::RolePermission => Entity::has_many(super::role_permission::Entity).into(), - Self::UserRole => Entity::has_many(super::user_role::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::RolePermission.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserRole.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/role_permission.rs b/pagetop-user/src/entity/role_permission.rs deleted file mode 100644 index 2c2859d1..00000000 --- a/pagetop-user/src/entity/role_permission.rs +++ /dev/null @@ -1,35 +0,0 @@ -use pagetop::db::entity::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "role_permission")] -pub struct Model { - #[sea_orm(primary_key)] - pub rid : u32, - #[sea_orm(primary_key)] - pub permission: String, - pub module : String, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - Role, -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::Role => Entity::belongs_to(super::role::Entity) - .from(Column::Rid) - .to(super::role::Column::Rid) - .into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Role.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/user.rs b/pagetop-user/src/entity/user.rs deleted file mode 100644 index 8bec2f1e..00000000 --- a/pagetop-user/src/entity/user.rs +++ /dev/null @@ -1,39 +0,0 @@ -use pagetop::db::entity::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "user")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub uid : u32, - #[sea_orm(unique)] - pub name : String, - pub pass : String, - pub mail : Option, - pub created : DateTimeUtc, - pub changed : DateTimeUtc, - pub access : DateTimeUtc, - pub login : DateTimeUtc, - pub status : bool, - pub timezone: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - UserRole, -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::UserRole => Entity::has_many(super::user_role::Entity).into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserRole.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/entity/user_role.rs b/pagetop-user/src/entity/user_role.rs deleted file mode 100644 index 23a6af8f..00000000 --- a/pagetop-user/src/entity/user_role.rs +++ /dev/null @@ -1,45 +0,0 @@ -use pagetop::db::entity::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] -#[sea_orm(table_name = "user_role")] -pub struct Model { - #[sea_orm(primary_key)] - pub uid: u32, - #[sea_orm(primary_key)] - pub rid: u32, -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation { - User, - Role, -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - match self { - Self::User => Entity::belongs_to(super::user::Entity) - .from(Column::Uid) - .to(super::user::Column::Uid) - .into(), - Self::Role => Entity::belongs_to(super::role::Entity) - .from(Column::Rid) - .to(super::role::Column::Rid) - .into(), - } - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Role.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 4059cc79..a55ea4e8 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -2,7 +2,6 @@ use pagetop::prelude::*; localize!("src/locales"); -mod entity; mod migration; pub struct UserModule; From f32f69dde73ed1dd78ce8c0b56ad8ab2b8501358 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 23 Apr 2022 21:23:00 +0200 Subject: [PATCH 28/80] Elimina downcast_rs y codifica componentes con Any --- pagetop/Cargo.toml | 1 - pagetop/src/base/component/block.rs | 4 ++++ pagetop/src/base/component/chunck.rs | 4 ++++ pagetop/src/base/component/container.rs | 4 ++++ pagetop/src/base/component/form/button.rs | 4 ++++ pagetop/src/base/component/form/date.rs | 4 ++++ pagetop/src/base/component/form/form.rs | 4 ++++ pagetop/src/base/component/form/hidden.rs | 4 ++++ pagetop/src/base/component/form/input.rs | 4 ++++ pagetop/src/base/component/grid/column.rs | 4 ++++ pagetop/src/base/component/grid/row.rs | 4 ++++ pagetop/src/base/component/image.rs | 4 ++++ pagetop/src/base/component/menu.rs | 8 ++++++++ pagetop/src/base/theme/bulmix/mod.rs | 4 ++-- pagetop/src/response/page/component.rs | 10 +++++----- pagetop/src/response/page/mod.rs | 2 +- 16 files changed, 60 insertions(+), 9 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index b058c7b4..bd2ba3a1 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -24,7 +24,6 @@ categories = [ [dependencies] concat-string = "1.0.1" doc-comment = "0.3.3" -downcast-rs = "1.2.0" figlet-rs = "0.1.3" futures = "0.3.21" once_cell = "1.10.0" diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 86370ff4..4c2ab0ab 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -45,6 +45,10 @@ impl PageComponent for Block { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Block { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 6dbc0ff1..fa6da576 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -28,6 +28,10 @@ impl PageComponent for Chunck { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { (*self.html()) } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Chunck { diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index fab8225a..de4daedc 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -72,6 +72,10 @@ impl PageComponent for Container { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Container { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 4c75dc62..5a2938a0 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -65,6 +65,10 @@ impl PageComponent for Button { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Button { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 10e795cb..b7d3924c 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -84,6 +84,10 @@ impl PageComponent for Date { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Date { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 73581ca2..67b9cd73 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -54,6 +54,10 @@ impl PageComponent for Form { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Form { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 736aa4ce..4c303e4d 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -28,6 +28,10 @@ impl PageComponent for Hidden { input type="hidden" id=[id] name=[self.name()] value=[self.value()]; } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Hidden { diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 71d801b7..21a34a53 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -112,6 +112,10 @@ impl PageComponent for Input { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Input { diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 77512ea2..58d3648f 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -40,6 +40,10 @@ impl PageComponent for Column { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Column { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 4574b090..6630901c 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -40,6 +40,10 @@ impl PageComponent for Row { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Row { diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 62690679..aaa96d86 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -37,6 +37,10 @@ impl PageComponent for Image { class=[self.classes()]; } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Image { diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 68c5c97e..6e052194 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -67,6 +67,10 @@ impl PageComponent for MenuItem { MenuItemType::Void => html! {}, } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl MenuItem { @@ -217,6 +221,10 @@ impl PageComponent for Menu { } } } + + fn as_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Menu { diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index c7aa3cb2..d6fd116b 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -39,11 +39,11 @@ impl ThemeTrait for BulmixTheme { ) { match component.name() { "GridRow" => { - let row = component.downcast_mut::().unwrap(); + let row = component.as_any().downcast_mut::().unwrap(); row.alter_classes("columns", ClassesOp::SetDefault); }, "GridColumn" => { - let col = component.downcast_mut::().unwrap(); + let col = component.as_any().downcast_mut::().unwrap(); col.alter_classes("column", ClassesOp::SetDefault); }, _ => {}, diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 05528fc8..d58258a4 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -1,11 +1,11 @@ use crate::html::{Markup, html}; use crate::response::page::PageAssets; -use downcast_rs::{Downcast, impl_downcast}; - use std::any::type_name; -pub trait PageComponent: Downcast + Send + Sync { +pub use std::any::Any as AnyComponent; + +pub trait PageComponent: AnyComponent + Send + Sync { fn new() -> Self where Self: Sized; @@ -41,6 +41,6 @@ pub trait PageComponent: Downcast + Send + Sync { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! {} } -} -impl_downcast!(PageComponent); + fn as_any(&mut self) -> &mut dyn AnyComponent; +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 527f74f9..e238954b 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -7,7 +7,7 @@ pub use assets::{ }; mod component; -pub use component::PageComponent; +pub use component::{AnyComponent, PageComponent}; mod container; pub use container::PageContainer; From 6de248f630b0936b9a771918479e5b77d3e3cadf Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 23 Apr 2022 21:25:21 +0200 Subject: [PATCH 29/80] Elimina downcast_rs y codifica componentes con Any --- pagetop/Cargo.toml | 1 - pagetop/src/base/component/block.rs | 4 ++++ pagetop/src/base/component/chunck.rs | 4 ++++ pagetop/src/base/component/container.rs | 4 ++++ pagetop/src/base/component/form/button.rs | 4 ++++ pagetop/src/base/component/form/date.rs | 4 ++++ pagetop/src/base/component/form/form.rs | 4 ++++ pagetop/src/base/component/form/hidden.rs | 4 ++++ pagetop/src/base/component/form/input.rs | 4 ++++ pagetop/src/base/component/grid/column.rs | 4 ++++ pagetop/src/base/component/grid/row.rs | 4 ++++ pagetop/src/base/component/image.rs | 4 ++++ pagetop/src/base/component/menu.rs | 8 ++++++++ pagetop/src/base/theme/bulmix/mod.rs | 4 ++-- pagetop/src/response/page/component.rs | 10 +++++----- pagetop/src/response/page/mod.rs | 2 +- 16 files changed, 60 insertions(+), 9 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index b058c7b4..bd2ba3a1 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -24,7 +24,6 @@ categories = [ [dependencies] concat-string = "1.0.1" doc-comment = "0.3.3" -downcast-rs = "1.2.0" figlet-rs = "0.1.3" futures = "0.3.21" once_cell = "1.10.0" diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 86370ff4..697c9344 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -45,6 +45,10 @@ impl PageComponent for Block { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Block { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 6dbc0ff1..2957671e 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -28,6 +28,10 @@ impl PageComponent for Chunck { fn default_render(&self, _: &mut PageAssets) -> Markup { html! { (*self.html()) } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Chunck { diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index fab8225a..e4e9589c 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -72,6 +72,10 @@ impl PageComponent for Container { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Container { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 4c75dc62..e098ea71 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -65,6 +65,10 @@ impl PageComponent for Button { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Button { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 10e795cb..bb7e0618 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -84,6 +84,10 @@ impl PageComponent for Date { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Date { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 73581ca2..1ff77394 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -54,6 +54,10 @@ impl PageComponent for Form { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Form { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 736aa4ce..24d70cb2 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -28,6 +28,10 @@ impl PageComponent for Hidden { input type="hidden" id=[id] name=[self.name()] value=[self.value()]; } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Hidden { diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 71d801b7..35a38e73 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -112,6 +112,10 @@ impl PageComponent for Input { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Input { diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 77512ea2..56dc2345 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -40,6 +40,10 @@ impl PageComponent for Column { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Column { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 4574b090..31739359 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -40,6 +40,10 @@ impl PageComponent for Row { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Row { diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 62690679..abafcdbf 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -37,6 +37,10 @@ impl PageComponent for Image { class=[self.classes()]; } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Image { diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 68c5c97e..b9461ed2 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -67,6 +67,10 @@ impl PageComponent for MenuItem { MenuItemType::Void => html! {}, } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl MenuItem { @@ -217,6 +221,10 @@ impl PageComponent for Menu { } } } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } } impl Menu { diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index c7aa3cb2..340b8c35 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -39,11 +39,11 @@ impl ThemeTrait for BulmixTheme { ) { match component.name() { "GridRow" => { - let row = component.downcast_mut::().unwrap(); + let row = component.as_mut_any().downcast_mut::().unwrap(); row.alter_classes("columns", ClassesOp::SetDefault); }, "GridColumn" => { - let col = component.downcast_mut::().unwrap(); + let col = component.as_mut_any().downcast_mut::().unwrap(); col.alter_classes("column", ClassesOp::SetDefault); }, _ => {}, diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 05528fc8..9e731e47 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -1,11 +1,11 @@ use crate::html::{Markup, html}; use crate::response::page::PageAssets; -use downcast_rs::{Downcast, impl_downcast}; - use std::any::type_name; -pub trait PageComponent: Downcast + Send + Sync { +pub use std::any::Any as AnyComponent; + +pub trait PageComponent: AnyComponent + Send + Sync { fn new() -> Self where Self: Sized; @@ -41,6 +41,6 @@ pub trait PageComponent: Downcast + Send + Sync { fn default_render(&self, assets: &mut PageAssets) -> Markup { html! {} } -} -impl_downcast!(PageComponent); + fn as_mut_any(&mut self) -> &mut dyn AnyComponent; +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 527f74f9..e238954b 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -7,7 +7,7 @@ pub use assets::{ }; mod component; -pub use component::PageComponent; +pub use component::{AnyComponent, PageComponent}; mod container; pub use container::PageContainer; From 0220020f4f9b3ab9c2ee04bce4da6210b14058f6 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 23 Apr 2022 21:55:37 +0200 Subject: [PATCH 30/80] =?UTF-8?q?A=C3=B1ade=20funci=C3=B3n=20as=5Fany()=20?= =?UTF-8?q?en=20componentes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/block.rs | 4 ++++ pagetop/src/base/component/chunck.rs | 4 ++++ pagetop/src/base/component/container.rs | 4 ++++ pagetop/src/base/component/form/button.rs | 4 ++++ pagetop/src/base/component/form/date.rs | 4 ++++ pagetop/src/base/component/form/form.rs | 4 ++++ pagetop/src/base/component/form/hidden.rs | 4 ++++ pagetop/src/base/component/form/input.rs | 4 ++++ pagetop/src/base/component/grid/column.rs | 4 ++++ pagetop/src/base/component/grid/row.rs | 4 ++++ pagetop/src/base/component/image.rs | 4 ++++ pagetop/src/base/component/menu.rs | 8 ++++++++ pagetop/src/response/page/component.rs | 2 ++ pagetop/src/theme/definition.rs | 4 ++-- 14 files changed, 56 insertions(+), 2 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 697c9344..e75981cd 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -46,6 +46,10 @@ impl PageComponent for Block { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 2957671e..9476e9d8 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -29,6 +29,10 @@ impl PageComponent for Chunck { html! { (*self.html()) } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index e4e9589c..553d1bae 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -73,6 +73,10 @@ impl PageComponent for Container { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index e098ea71..f6926233 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -66,6 +66,10 @@ impl PageComponent for Button { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index bb7e0618..0aa77a93 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -85,6 +85,10 @@ impl PageComponent for Date { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 1ff77394..5d41d4bc 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -55,6 +55,10 @@ impl PageComponent for Form { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 24d70cb2..a9ccbd47 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -29,6 +29,10 @@ impl PageComponent for Hidden { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 35a38e73..0bb5502d 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -113,6 +113,10 @@ impl PageComponent for Input { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 56dc2345..0e017f14 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -41,6 +41,10 @@ impl PageComponent for Column { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 31739359..9e48d34e 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -41,6 +41,10 @@ impl PageComponent for Row { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index abafcdbf..d2fc2caf 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -38,6 +38,10 @@ impl PageComponent for Image { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index b9461ed2..2ca9be57 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -68,6 +68,10 @@ impl PageComponent for MenuItem { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } @@ -222,6 +226,10 @@ impl PageComponent for Menu { } } + fn as_any(&mut self) -> &dyn AnyComponent { + self + } + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { self } diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 9e731e47..fb57f2ef 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -42,5 +42,7 @@ pub trait PageComponent: AnyComponent + Send + Sync { html! {} } + fn as_any(&mut self) -> &dyn AnyComponent; + fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 983bf0a6..29b20d4c 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -85,7 +85,7 @@ pub trait ThemeTrait: Send + Sync { match component.name() { "Block" => { - let block = component.downcast_mut::().unwrap(); + let block = component.as_mut_any().downcast_mut::().unwrap(); block.alter_title("New title"); }, _ => {}, @@ -105,7 +105,7 @@ pub trait ThemeTrait: Send + Sync { match component.name() { "Block" => { - let block = component.downcast_ref::().unwrap(); + let block = component.as_any().downcast_ref::().unwrap(); match block.template() { "default" => Some(block_default(block)), _ => None, From d4c6a3b2f3a499ce484d106272599373a07a572a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 23 Apr 2022 22:02:54 +0200 Subject: [PATCH 31/80] =?UTF-8?q?Corrige=20identificaci=C3=B3n=20de=20vari?= =?UTF-8?q?able=20mutable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/block.rs | 2 +- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 2 +- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 2 +- pagetop/src/base/component/grid/column.rs | 2 +- pagetop/src/base/component/grid/row.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 4 ++-- pagetop/src/response/page/component.rs | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index e75981cd..727ff86e 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -46,7 +46,7 @@ impl PageComponent for Block { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 9476e9d8..e0613d3b 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -29,7 +29,7 @@ impl PageComponent for Chunck { html! { (*self.html()) } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 553d1bae..86e907a9 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -73,7 +73,7 @@ impl PageComponent for Container { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index f6926233..7f7ada99 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -66,7 +66,7 @@ impl PageComponent for Button { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 0aa77a93..a062630d 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -85,7 +85,7 @@ impl PageComponent for Date { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 5d41d4bc..0470436f 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -55,7 +55,7 @@ impl PageComponent for Form { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index a9ccbd47..6e3edecc 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -29,7 +29,7 @@ impl PageComponent for Hidden { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 0bb5502d..01158ac5 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -113,7 +113,7 @@ impl PageComponent for Input { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 0e017f14..59948416 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -41,7 +41,7 @@ impl PageComponent for Column { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 9e48d34e..15b87cef 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -41,7 +41,7 @@ impl PageComponent for Row { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index d2fc2caf..0b4b4168 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -38,7 +38,7 @@ impl PageComponent for Image { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 2ca9be57..e5fb46cf 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -68,7 +68,7 @@ impl PageComponent for MenuItem { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } @@ -226,7 +226,7 @@ impl PageComponent for Menu { } } - fn as_any(&mut self) -> &dyn AnyComponent { + fn as_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index fb57f2ef..e4d6b61c 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -42,7 +42,7 @@ pub trait PageComponent: AnyComponent + Send + Sync { html! {} } - fn as_any(&mut self) -> &dyn AnyComponent; + fn as_any(&self) -> &dyn AnyComponent; fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } From e7f9bf8778e9638e98d6b7486cba863bb124db50 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 24 Apr 2022 18:44:37 +0200 Subject: [PATCH 32/80] =?UTF-8?q?A=C3=B1ade=20funciones=20de=20acceso=20b?= =?UTF-8?q?=C3=A1sico=20a=20base=20de=20datos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-node/src/lib.rs | 2 +- ...m20220316_000001_create_table_node_type.rs | 2 +- .../m20220316_000002_create_table_node.rs | 2 +- ...0220316_000003_create_table_node_access.rs | 2 +- ...20316_000004_create_table_node_revision.rs | 2 +- pagetop-user/src/lib.rs | 2 +- .../m20220312_000001_create_table_role.rs | 88 ++++++++++--------- ...312_000002_create_table_role_permission.rs | 2 +- .../m20220312_000003_create_table_user.rs | 2 +- ...m20220312_000004_create_table_user_role.rs | 2 +- pagetop/STARTER.bin.Cargo.toml | 2 - pagetop/STARTER.lib.Cargo.toml | 2 - pagetop/src/app/db.rs | 44 ++++++++-- pagetop/src/db.rs | 14 +-- pagetop/src/module/all.rs | 2 +- pagetop/src/module/definition.rs | 2 +- pagetop/src/prelude.rs | 2 +- 17 files changed, 99 insertions(+), 75 deletions(-) diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index 0f5c4662..a05800ec 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -24,7 +24,7 @@ impl ModuleTrait for NodeModule { cfg.route("/node", app::web::get().to(node)); } - fn migrations(&self) -> Vec> { + fn migrations(&self) -> Vec> { vec![ boxed_migration!(m20220316_000001_create_table_node_type), boxed_migration!(m20220316_000002_create_table_node), diff --git a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs index 5180a785..6ce9abe1 100644 --- a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs +++ b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; /// Stores information about all defined {node} types. #[derive(Iden)] diff --git a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs index fe65fc2c..927c92f9 100644 --- a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs +++ b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; /// The base table for nodes. #[derive(Iden)] diff --git a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs index a179240f..2b55da75 100644 --- a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs +++ b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; // Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes. #[derive(Iden)] diff --git a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs index 4dc4e1b6..5162407c 100644 --- a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs +++ b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; // Stores information about each saved version of a {node}. #[derive(Iden)] diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index a55ea4e8..d5d96f37 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -23,7 +23,7 @@ impl ModuleTrait for UserModule { cfg.route("/user/login", app::web::get().to(login)); } - fn migrations(&self) -> Vec> { + fn migrations(&self) -> Vec> { vec![ boxed_migration!(m20220312_000001_create_table_role), boxed_migration!(m20220312_000002_create_table_role_permission), diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs index af453f74..1028bb5a 100644 --- a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs +++ b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; #[derive(Iden)] enum Role { Table, @@ -12,49 +12,55 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - // Store user roles. - Table::create() - .table(Role::Table) - .if_not_exists() - // Primary Key: Unique role ID. - .col(ColumnDef::new(Role::Rid) - .unsigned() - .not_null() - .auto_increment() - .primary_key() - ) - // Unique role name. - .col(ColumnDef::new(Role::Name) - .string_len(64) - .not_null() - .unique_key() - ) - // The weight of this role in listings and the user interface. - .col(ColumnDef::new(Role::Weight) - .integer() - .not_null() - .default(0) - ) - // INDEXES. - .index(Index::create() - .name("name-weight") - .col(Role::Name) - .col(Role::Weight) - ) - .to_owned() - ) - .await + manager.create_table( + // Store user roles. + Table::create() + .table(Role::Table) + .if_not_exists() + // Primary Key: Unique role ID. + .col(ColumnDef::new(Role::Rid) + .unsigned() + .not_null() + .auto_increment() + .primary_key() + ) + // Unique role name. + .col(ColumnDef::new(Role::Name) + .string_len(64) + .not_null() + .unique_key() + ) + // The weight of this role in listings and the user interface. + .col(ColumnDef::new(Role::Weight) + .integer() + .not_null() + .default(0) + ) + // INDEXES. + .index(Index::create() + .name("name-weight") + .col(Role::Name) + .col(Role::Weight) + ) + .to_owned() + ) + .await?; + + app::db::exec::(Query::insert() + .into_table(Role::Table) + .columns(vec![Role::Name]) + .values_panic(vec!["anonymous".into()]) + .values_panic(vec!["authenticated".into()]) + ) + .await.map(|_| ()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(Role::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(Role::Table) + .to_owned() + ) + .await } } diff --git a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs index 0148af5f..3c997872 100644 --- a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs +++ b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; #[derive(Iden)] enum RolePermission { Table, diff --git a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs index bf151f50..2ef84287 100644 --- a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs +++ b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; #[derive(Iden)] enum User { Table, diff --git a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs index f92d019b..373f7e53 100644 --- a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs +++ b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs @@ -1,4 +1,4 @@ -use pagetop::db::migration::*; +use pagetop::prelude::*; #[derive(Iden)] enum UserRole { Table, diff --git a/pagetop/STARTER.bin.Cargo.toml b/pagetop/STARTER.bin.Cargo.toml index f9c6560f..f3169356 100644 --- a/pagetop/STARTER.bin.Cargo.toml +++ b/pagetop/STARTER.bin.Cargo.toml @@ -21,7 +21,5 @@ default-features = false actix-web = "3.3.3" # Si se usa la macro html!: maud = { version = "0.23.0" } -# Si se usa base de datos: -sea-orm = { version = "0.7.1" } # Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/STARTER.lib.Cargo.toml b/pagetop/STARTER.lib.Cargo.toml index 7a74f96e..c268b8cc 100644 --- a/pagetop/STARTER.lib.Cargo.toml +++ b/pagetop/STARTER.lib.Cargo.toml @@ -10,7 +10,5 @@ edition = "2021" pagetop = { path = "../pagetop" } # Si se usa la macro html!: maud = { version = "0.23.0" } -# Si se usa base de datos: -sea-orm = { version = "0.7.1" } # Si se requiere serialización de estructuras de datos: serde = { version = "1.0", features = ["derive"] } diff --git a/pagetop/src/app/db.rs b/pagetop/src/app/db.rs index 9d196970..aa3f0045 100644 --- a/pagetop/src/app/db.rs +++ b/pagetop/src/app/db.rs @@ -1,10 +1,11 @@ -use crate::{Lazy, db, run_now, trace}; +use crate::{Lazy, run_now, trace}; use crate::config::SETTINGS; +use crate::db::*; -use sea_orm::{ConnectOptions, Database}; +use sea_orm::{ConnectionTrait, ConnectOptions, Database, DatabaseBackend, Statement}; use tracing_unwrap::ResultExt; -pub static DBCONN: Lazy = Lazy::new(|| { +pub static DBCONN: Lazy = Lazy::new(|| { trace::info!( "Connecting to database \"{}\" using a pool of {} connections", &SETTINGS.database.db_name, @@ -13,7 +14,7 @@ pub static DBCONN: Lazy = Lazy::new(|| { let db_uri = match SETTINGS.database.db_type.as_str() { "mysql" | "postgres" => { - let mut tmp_uri = db::DbUri::parse(format!( + let mut tmp_uri = DbUri::parse(format!( "{}://{}/{}", &SETTINGS.database.db_type, &SETTINGS.database.db_host, @@ -33,7 +34,7 @@ pub static DBCONN: Lazy = Lazy::new(|| { } tmp_uri }, - "sqlite" => db::DbUri::parse( + "sqlite" => DbUri::parse( format!("{}://{}", &SETTINGS.database.db_type, &SETTINGS.database.db_name @@ -43,7 +44,7 @@ pub static DBCONN: Lazy = Lazy::new(|| { "Unrecognized database type \"{}\"", &SETTINGS.database.db_type ); - db::DbUri::parse("").unwrap() + DbUri::parse("").unwrap() } }; @@ -55,3 +56,34 @@ pub static DBCONN: Lazy = Lazy::new(|| { }) ).expect_or_log("Failed to connect to database") }); + +static DBBACKEND: Lazy = Lazy::new(|| { + DBCONN.get_database_backend() +}); + + +pub async fn query(stmt: &mut Q) -> Result, DbErr> { + DBCONN.query_all(Statement::from_string( + *DBBACKEND, + match *DBBACKEND { + DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder), + DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder), + DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder), + } + )).await +} + +pub async fn exec(stmt: &mut Q) -> Result, DbErr> { + DBCONN.query_one(Statement::from_string( + *DBBACKEND, + match *DBBACKEND { + DatabaseBackend::MySql => stmt.to_string(MysqlQueryBuilder), + DatabaseBackend::Postgres => stmt.to_string(PostgresQueryBuilder), + DatabaseBackend::Sqlite => stmt.to_string(SqliteQueryBuilder), + } + )).await +} + +pub async fn exec_raw(stmt: String) -> Result { + DBCONN.execute(Statement::from_string(*DBBACKEND, stmt)).await +} diff --git a/pagetop/src/db.rs b/pagetop/src/db.rs index 550f8f66..4b35bd59 100644 --- a/pagetop/src/db.rs +++ b/pagetop/src/db.rs @@ -1,18 +1,8 @@ pub use url::Url as DbUri; -pub use sea_orm::{ - DbErr, - DatabaseConnection as DbConn, -}; +pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult}; -pub mod entity { - pub use sea_orm::entity::prelude::*; -} - -pub mod migration { - pub use sea_schema::migration::prelude::*; - pub use crate::module_name; -} +pub use sea_schema::migration::prelude::*; #[macro_export] macro_rules! boxed_migration { diff --git a/pagetop/src/module/all.rs b/pagetop/src/module/all.rs index c95583e9..6380917a 100644 --- a/pagetop/src/module/all.rs +++ b/pagetop/src/module/all.rs @@ -1,5 +1,5 @@ use crate::{Lazy, app, run_now, trace}; -use crate::db::migration::*; +use crate::db::*; use super::ModuleTrait; use std::sync::RwLock; diff --git a/pagetop/src/module/definition.rs b/pagetop/src/module/definition.rs index b01f9801..a3affa2f 100644 --- a/pagetop/src/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -23,7 +23,7 @@ pub trait ModuleTrait: Send + Sync { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[allow(unused_variables)] - fn migrations(&self) -> Vec> { + fn migrations(&self) -> Vec> { vec![] } } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 55c9681e..4cbd9a7d 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -13,7 +13,7 @@ pub use crate::trace; pub use crate::localize; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub use crate::{db, boxed_migration}; +pub use crate::{db, db::*, boxed_migration}; pub use crate::html::*; pub use crate::theme::*; From f30f84e993fe68efed5af49f2b887edee25278ad Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 24 Apr 2022 21:57:07 +0200 Subject: [PATCH 33/80] =?UTF-8?q?Actualiza=20formato=20del=20c=C3=B3digo?= =?UTF-8?q?=20de=20las=20migraciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...m20220316_000001_create_table_node_type.rs | 146 +++++++------- .../m20220316_000002_create_table_node.rs | 189 +++++++++--------- ...0220316_000003_create_table_node_access.rs | 109 +++++----- ...20316_000004_create_table_node_revision.rs | 147 +++++++------- .../m20220312_000001_create_table_role.rs | 67 +++---- ...312_000002_create_table_role_permission.rs | 100 +++++---- .../m20220312_000003_create_table_user.rs | 138 ++++++------- ...m20220312_000004_create_table_user_role.rs | 102 +++++----- 8 files changed, 486 insertions(+), 512 deletions(-) diff --git a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs index 6ce9abe1..831a3396 100644 --- a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs +++ b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs @@ -1,90 +1,90 @@ use pagetop::prelude::*; -/// Stores information about all defined {node} types. #[derive(Iden)] enum NodeType { - Table, // Nombre de la tabla: node_type (Tipo de nodo). - Type, // The machine-readable name of this type - Name, // The human-readable name of this type - Description, // Descripción breve del tipo. - Help, // Help information shown to the user when creating a {node} of this type - HasTitle, // Boolean indicating whether this type uses the {node}.title field - TitleLabel, // The label displayed for the title field on the edit form - Custom, // A boolean indicating whether this type is defined by a module (FALSE) or by a user via Add content type (TRUE) - Locked, // A boolean indicating whether the administrator can change the machine name of this type - Disabled, // A boolean indicating whether the node type is disabled - OrigType, // The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0 + Table, // Stores information about all defined Node types. + + Type, // The machine-readable name of this type. + Name, // The human-readable name of this type. + Description, // Descripción breve del tipo. + Help, // Help information shown to the user when creating a Node of this type. + HasTitle, // Boolean indicating whether this type uses the Node.Title field. + TitleLabel, // The label displayed for the title field on the edit form. + Custom, // A boolean indicating whether this type is defined by a module (FALSE) or + // by a user via Add content type (TRUE). + Locked, // A boolean indicating whether the administrator can change the machine + // name of this type. + Disabled, // A boolean indicating whether the node type is disabled. + OrigType, // The original machine-readable name of this node type, this may be + // different from the current type name if the locked field is 0. } pub struct Migration; -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20220316_000001_create_table_node_type" - } -} - #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(NodeType::Table) - .if_not_exists() - .col(ColumnDef::new(NodeType::Type) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(NodeType::Name) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::Description) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::Help) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::HasTitle) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::TitleLabel) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::Custom) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::Locked) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::Disabled) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeType::OrigType) - .string() - .not_null() - ) - .to_owned() + manager.create_table(Table::create() + .table(NodeType::Table) + .if_not_exists() + .col(ColumnDef::new(NodeType::Type) + .integer() + .not_null() + .auto_increment() + .primary_key(), ) - .await + .col(ColumnDef::new(NodeType::Name) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Description) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Help) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::HasTitle) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::TitleLabel) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Custom) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Locked) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::Disabled) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeType::OrigType) + .string() + .not_null() + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(NodeType::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(NodeType::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() } } diff --git a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs index 927c92f9..0b70860d 100644 --- a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs +++ b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs @@ -1,110 +1,113 @@ use pagetop::prelude::*; -/// The base table for nodes. #[derive(Iden)] enum Node { - Table, // Nombre de la tabla: node (Nodo). - Nid, // The primary identifier for a node - Vid, // The current {node_revision}.vid version identifier - Type, // The {node_type}.type of this node - Language, // The {languages}.language of this node - Title, // The title of this node, always treated as non-markup plain text - Uid, // The {users}.uid that owns this node; initially, this is the user that created it - Status, // Boolean indicating whether the node is published (visible to non-administrators) - Created, // The Unix timestamp when the node was created - Changed, // The Unix timestamp when the node was most recently saved - Comment, // Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write) - Promote, // Boolean indicating whether the node should be displayed on the front page - Sticky, // Boolean indicating whether the node should be displayed at the top of lists in which it appears - Tnid, // The translation set id for this node, which equals the node id of the source post in each set - Translate, // A boolean indicating whether this translation page needs to be updated + Table, // The base table for nodes. + + Nid, // The primary identifier for a node. + Vid, // The current {node_revision}.vid version identifier. + Type, // The {node_type}.type of this node. + Language, // The {languages}.language of this node. + Title, // The title of this node, always treated as non-markup plain text. + Uid, // The {users}.uid that owns this node; initially, this is the user that + // created it. + Status, // Boolean indicating whether the node is published (visible to + // non-administrators). + Created, // The Unix timestamp when the node was created. + Changed, // The Unix timestamp when the node was most recently saved. + Comment, // Whether comments are allowed on this node: 0 = no, 1 = closed (read + // only), 2 = open (read/write). + Promote, // Boolean indicating whether the node should be displayed on the front + // page. + Sticky, // Boolean indicating whether the node should be displayed at the top of + // lists in which it appears. + Tnid, // The translation set id for this node, which equals the node id of the + // source post in each set. + Translate, // A boolean indicating whether this translation page needs to be updated. } pub struct Migration; -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20220316_000002_create_table_node" - } -} - #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(Node::Table) - .if_not_exists() - .col(ColumnDef::new(Node::Nid) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(Node::Vid) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Type) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Language) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Title) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Uid) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Status) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Created) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Changed) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Comment) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Promote) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Sticky) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Tnid) - .string() - .not_null() - ) - .col(ColumnDef::new(Node::Translate) - .string() - .not_null() - ) - .to_owned() + manager.create_table(Table::create() + .table(Node::Table) + .if_not_exists() + .col(ColumnDef::new(Node::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), ) - .await + .col(ColumnDef::new(Node::Vid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Type) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Language) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Title) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Uid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Status) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Created) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Changed) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Comment) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Promote) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Sticky) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Tnid) + .string() + .not_null() + ) + .col(ColumnDef::new(Node::Translate) + .string() + .not_null() + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(Node::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(Node::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() } } diff --git a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs index 2b55da75..8252b5d0 100644 --- a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs +++ b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs @@ -1,70 +1,73 @@ use pagetop::prelude::*; -// Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes. #[derive(Iden)] enum NodeAccess { - Table, // Nombre de la tabla: node_access (Acceso a nodos). - Nid, // The {node}.nid this record affects - Gid, // The grant ID a user must possess in the specified realm to gain this row's privileges on the node - Realm, // The realm in which the user must possess the grant ID. Each node access node can define one or more realms - GrantView, // Boolean indicating whether a user with the realm/grant pair can view this node - GrantUpdate, // Boolean indicating whether a user with the realm/grant pair can edit this node - GrantDelete, // Boolean indicating whether a user with the realm/grant pair can delete this node + Table, // Identifies which realm/grant pairs a user must possess in order to view, + // update, or delete specific nodes. + + Nid, // The {node}.nid this record affects. + Gid, // The grant ID a user must possess in the specified realm to gain this + // row's privileges on the node. + Realm, // The realm in which the user must possess the grant ID. Each node access + // node can define one or more realms. + GrantView, // Boolean indicating whether a user with the realm/grant pair can view this + // node. + GrantUpdate, // Boolean indicating whether a user with the realm/grant pair can edit this + // node. + GrantDelete, // Boolean indicating whether a user with the realm/grant pair can delete + // this node. } pub struct Migration; -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20220316_000003_create_table_node_access" - } -} - #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(NodeAccess::Table) - .if_not_exists() - .col(ColumnDef::new(NodeAccess::Nid) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(NodeAccess::Gid) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeAccess::Realm) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeAccess::GrantView) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeAccess::GrantUpdate) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeAccess::GrantDelete) - .string() - .not_null() - ) - .to_owned() + manager.create_table(Table::create() + .table(NodeAccess::Table) + .if_not_exists() + .col(ColumnDef::new(NodeAccess::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), ) - .await + .col(ColumnDef::new(NodeAccess::Gid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::Realm) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantView) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantUpdate) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeAccess::GrantDelete) + .string() + .not_null() + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(NodeAccess::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(NodeAccess::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() } } diff --git a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs index 5162407c..9c414a60 100644 --- a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs +++ b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs @@ -1,90 +1,91 @@ use pagetop::prelude::*; -// Stores information about each saved version of a {node}. #[derive(Iden)] enum NodeRevision { - Table, // Nombre de la tabla: node_revisión (Versiones de nodos). - Nid, // The {node} this version belongs to - Vid, // The primary identifier for this version - Uid, // The {users}.uid that created this version - Title, // The title of this version - Log, // The log entry explaining the changes in this version - Timestamp, // A Unix timestamp indicating when this version was created - Status, // Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators) - Comment, // Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write) - Promote, // Boolean indicating whether the node (at the time of this revision) should be displayed on the front page - Sticky, // Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears + Table, // Stores information about each saved version of a {node}. + + Nid, // The {node} this version belongs to. + Vid, // The primary identifier for this version. + Uid, // The {users}.uid that created this version. + Title, // The title of this version. + Log, // The log entry explaining the changes in this version. + Timestamp, // A Unix timestamp indicating when this version was created. + Status, // Boolean indicating whether the node (at the time of this revision) is + // published (visible to non-administrators). + Comment, // Whether comments are allowed on this node (at the time of this revision): + // 0 = no, 1 = closed (read only), 2 = open (read/write). + Promote, // Boolean indicating whether the node (at the time of this revision) should + // be displayed on the front page. + Sticky, // Boolean indicating whether the node (at the time of this revision) should + // be displayed at the top of lists in which it appears. } pub struct Migration; -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20220316_000004_create_table_node_revision" - } -} - #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(NodeRevision::Table) - .if_not_exists() - .col(ColumnDef::new(NodeRevision::Nid) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(NodeRevision::Vid) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Uid) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Title) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Log) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Timestamp) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Status) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Comment) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Promote) - .string() - .not_null() - ) - .col(ColumnDef::new(NodeRevision::Sticky) - .string() - .not_null() - ) - .to_owned() + manager.create_table(Table::create() + .table(NodeRevision::Table) + .if_not_exists() + .col(ColumnDef::new(NodeRevision::Nid) + .integer() + .not_null() + .auto_increment() + .primary_key(), ) - .await + .col(ColumnDef::new(NodeRevision::Vid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Uid) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Title) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Log) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Timestamp) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Status) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Comment) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Promote) + .string() + .not_null() + ) + .col(ColumnDef::new(NodeRevision::Sticky) + .string() + .not_null() + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(NodeRevision::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(NodeRevision::Table) + .to_owned() + ) + .await + } +} + +impl MigrationName for Migration { + fn name(&self) -> &str { + module_name!() } } diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs index 1028bb5a..61d21372 100644 --- a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs +++ b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs @@ -1,10 +1,12 @@ use pagetop::prelude::*; #[derive(Iden)] -enum Role { Table, - Rid, - Name, - Weight, +enum Role { + Table, // Store user roles. + + Rid, // Primary Key: Unique role ID. + Name, // Unique role name. + Weight, // The weight of this role in listings and the user interface. } pub struct Migration; @@ -12,37 +14,32 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager.create_table( - // Store user roles. - Table::create() - .table(Role::Table) - .if_not_exists() - // Primary Key: Unique role ID. - .col(ColumnDef::new(Role::Rid) - .unsigned() - .not_null() - .auto_increment() - .primary_key() - ) - // Unique role name. - .col(ColumnDef::new(Role::Name) - .string_len(64) - .not_null() - .unique_key() - ) - // The weight of this role in listings and the user interface. - .col(ColumnDef::new(Role::Weight) - .integer() - .not_null() - .default(0) - ) - // INDEXES. - .index(Index::create() - .name("name-weight") - .col(Role::Name) - .col(Role::Weight) - ) - .to_owned() + manager.create_table(Table::create() + .table(Role::Table) + .if_not_exists() + .col(ColumnDef::new(Role::Rid) + .unsigned() + .not_null() + .auto_increment() + .primary_key() + ) + .col(ColumnDef::new(Role::Name) + .string_len(64) + .not_null() + .unique_key() + ) + .col(ColumnDef::new(Role::Weight) + .integer() + .not_null() + .default(0) + ) + // INDEXES. + .index(Index::create() + .name("name-weight") + .col(Role::Name) + .col(Role::Weight) + ) + .to_owned() ) .await?; diff --git a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs index 3c997872..d5e5f8f1 100644 --- a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs +++ b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs @@ -1,72 +1,64 @@ use pagetop::prelude::*; #[derive(Iden)] -enum RolePermission { Table, - Rid, - Permission, - Module, +enum RolePermission { + Table, // Stores the permissions assigned to user roles. + + Rid, // Foreign Key: Role::Rid. + Permission, // A single permission granted to the role identified by Rid. + Module, // The module declaring the permission. } + #[derive(Iden)] -enum Role { Table, - Rid, -// ... -} +enum Role { Table, Rid, /* ... */ } pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - // Stores the permissions assigned to user roles. - Table::create() - .table(RolePermission::Table) - .if_not_exists() - // Foreign Key: Role::Rid. - .col(ColumnDef::new(RolePermission::Rid) - .unsigned() - .not_null() - ) - // A single permission granted to the role identified by Rid. - .col(ColumnDef::new(RolePermission::Permission) - .string_len(128) - .not_null() - ) - // The module declaring the permission. - .col(ColumnDef::new(RolePermission::Module) - .string_len(255) - .not_null() - ) - // INDEXES. - .primary_key(Index::create() - .col(RolePermission::Rid) - .col(RolePermission::Permission) - ) - .index(Index::create() - .name("permission") - .col(RolePermission::Permission) - ) - .foreign_key( - ForeignKey::create() - .name("fk_role_permission-rid") - .from(RolePermission::Table, RolePermission::Rid) - .to(Role::Table, Role::Rid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) - ) - .to_owned() + manager.create_table(Table::create() + .table(RolePermission::Table) + .if_not_exists() + .col(ColumnDef::new(RolePermission::Rid) + .unsigned() + .not_null() ) - .await + .col(ColumnDef::new(RolePermission::Permission) + .string_len(128) + .not_null() + ) + .col(ColumnDef::new(RolePermission::Module) + .string_len(255) + .not_null() + ) + // INDEXES. + .primary_key(Index::create() + .col(RolePermission::Rid) + .col(RolePermission::Permission) + ) + .index(Index::create() + .name("permission") + .col(RolePermission::Permission) + ) + .foreign_key(ForeignKey::create() + .name("fk_role_permission-rid") + .from(RolePermission::Table, RolePermission::Rid) + .to(Role::Table, Role::Rid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(RolePermission::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(RolePermission::Table) + .to_owned() + ) + .await } } diff --git a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs index 2ef84287..4849eae5 100644 --- a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs +++ b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs @@ -1,17 +1,19 @@ use pagetop::prelude::*; #[derive(Iden)] -enum User { Table, - Uid, - Name, - Pass, - Mail, - Created, - Changed, - Access, - Login, - Status, - Timezone, +enum User { + Table, // Stores user data. + + Uid, // Primary Key: Unique user ID. + Name, // Unique user name. + Pass, // User's password (hashed). + Mail, // User's e-mail address. + Created, // Timestamp for when user was created. + Changed, // Timestamp for when user was changed. + Access, // Timestamp for previous time user accessed the site. + Login, // Timestamp for user's last login. + Status, // Whether the user is active(1) or blocked(0). + Timezone, // User's time zone. } pub struct Migration; @@ -19,74 +21,60 @@ pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - // Stores user data. - Table::create() - .table(User::Table) - .if_not_exists() - // Primary Key: Unique user ID. - .col(ColumnDef::new(User::Uid) - .unsigned() - .not_null() - .primary_key() - ) - // Unique user name. - .col(ColumnDef::new(User::Name) - .string_len(60) - .not_null() - .unique_key() - ) - // User's password (hashed). - .col(ColumnDef::new(User::Pass) - .string_len(128) - .not_null() - ) - // User's e-mail address. - .col(ColumnDef::new(User::Mail) - .string_len(255) - ) - // Timestamp for when user was created. - .col(ColumnDef::new(User::Created) - .timestamp() - .not_null() - ) - // Timestamp for when user was changed. - .col(ColumnDef::new(User::Changed) - .timestamp() - .not_null() - ) - // Timestamp for previous time user accessed the site. - .col(ColumnDef::new(User::Access) - .timestamp() - .not_null() - ) - // Timestamp for user's last login. - .col(ColumnDef::new(User::Login) - .timestamp() - .not_null() - ) - // Whether the user is active(1) or blocked(0). - .col(ColumnDef::new(User::Status) - .boolean() - .not_null() - ) - // User's time zone. - .col(ColumnDef::new(User::Timezone) - .string_len(32) - ) - .to_owned() + manager.create_table(Table::create() + .table(User::Table) + .if_not_exists() + .col(ColumnDef::new(User::Uid) + .unsigned() + .not_null() + .primary_key() ) - .await + .col(ColumnDef::new(User::Name) + .string_len(60) + .not_null() + .unique_key() + ) + .col(ColumnDef::new(User::Pass) + .string_len(128) + .not_null() + ) + .col(ColumnDef::new(User::Mail) + .string_len(255) + ) + .col(ColumnDef::new(User::Created) + .timestamp() + .not_null() + ) + .col(ColumnDef::new(User::Changed) + .timestamp() + .not_null() + ) + .col(ColumnDef::new(User::Access) + .timestamp() + .not_null() + ) + .col(ColumnDef::new(User::Login) + .timestamp() + .not_null() + ) + .col(ColumnDef::new(User::Status) + .boolean() + .not_null() + ) + .col(ColumnDef::new(User::Timezone) + .string_len(32) + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(User::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(User::Table) + .to_owned() + ) + .await } } diff --git a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs index 373f7e53..1b15810c 100644 --- a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs +++ b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs @@ -1,75 +1,65 @@ use pagetop::prelude::*; #[derive(Iden)] -enum UserRole { Table, - Uid, - Rid, +enum UserRole { + Table, // Maps users to roles. + + Uid, // Foreign Key: User::Uid for user. + Rid, // Foreign Key: Role::Rid for role. } + #[derive(Iden)] -enum User { Table, - Uid, -// ... -} +enum User { Table, Uid, /* ... */ } + #[derive(Iden)] -enum Role { Table, - Rid, -// ... -} +enum Role { Table, Rid, /* ... */ } pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - // Maps users to roles. - Table::create() - .table(UserRole::Table) - .if_not_exists() - // Foreign Key: User::Uid for user. - .col(ColumnDef::new(UserRole::Uid) - .unsigned() - .not_null() - ) - // Foreign Key: Role::Rid for role. - .col(ColumnDef::new(UserRole::Rid) - .unsigned() - .not_null() - ) - // INDEXES. - .primary_key(Index::create() - .col(UserRole::Uid) - .col(UserRole::Rid) - ) - .foreign_key( - ForeignKey::create() - .name("fk_user_role-uid") - .from(UserRole::Table, UserRole::Uid) - .to(User::Table, User::Uid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) - ) - .foreign_key( - ForeignKey::create() - .name("fk_user_role-rid") - .from(UserRole::Table, UserRole::Rid) - .to(Role::Table, Role::Rid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) - ) - .to_owned() + manager.create_table(Table::create() + .table(UserRole::Table) + .if_not_exists() + .col(ColumnDef::new(UserRole::Uid) + .unsigned() + .not_null() ) - .await + .col(ColumnDef::new(UserRole::Rid) + .unsigned() + .not_null() + ) + // INDEXES. + .primary_key(Index::create() + .col(UserRole::Uid) + .col(UserRole::Rid) + ) + .foreign_key(ForeignKey::create() + .name("fk_user_role-uid") + .from(UserRole::Table, UserRole::Uid) + .to(User::Table, User::Uid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .foreign_key(ForeignKey::create() + .name("fk_user_role-rid") + .from(UserRole::Table, UserRole::Rid) + .to(Role::Table, Role::Rid) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade) + ) + .to_owned() + ) + .await } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop() - .table(UserRole::Table) - .to_owned() - ) - .await + manager.drop_table(Table::drop() + .table(UserRole::Table) + .to_owned() + ) + .await } } From 42a4731bdda2be44742455eceb7ed971f9625ccd Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 25 Apr 2022 20:57:36 +0200 Subject: [PATCH 34/80] Retoca las migraciones principales --- .../m20220316_000001_create_table_node_type.rs | 2 +- .../m20220316_000002_create_table_node.rs | 8 ++++---- .../m20220316_000003_create_table_node_access.rs | 6 +++--- ...20220316_000004_create_table_node_revision.rs | 6 +++--- .../m20220312_000001_create_table_role.rs | 16 +++++++++------- ...220312_000002_create_table_role_permission.rs | 11 +++-------- .../m20220312_000003_create_table_user.rs | 2 +- .../m20220312_000004_create_table_user_role.rs | 10 +++++----- 8 files changed, 29 insertions(+), 32 deletions(-) diff --git a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs index 831a3396..50117825 100644 --- a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs +++ b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs @@ -2,7 +2,7 @@ use pagetop::prelude::*; #[derive(Iden)] enum NodeType { - Table, // Stores information about all defined Node types. + Table, // node_type: Stores information about all defined Node types. Type, // The machine-readable name of this type. Name, // The human-readable name of this type. diff --git a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs index 0b70860d..62e2bda1 100644 --- a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs +++ b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs @@ -2,14 +2,14 @@ use pagetop::prelude::*; #[derive(Iden)] enum Node { - Table, // The base table for nodes. + Table, // node: The base table for nodes. Nid, // The primary identifier for a node. - Vid, // The current {node_revision}.vid version identifier. - Type, // The {node_type}.type of this node. + Vid, // The current NodeRevision.vid version identifier. + Type, // The NodeType.type of this node. Language, // The {languages}.language of this node. Title, // The title of this node, always treated as non-markup plain text. - Uid, // The {users}.uid that owns this node; initially, this is the user that + Uid, // The User.uid that owns this node; initially, this is the user that // created it. Status, // Boolean indicating whether the node is published (visible to // non-administrators). diff --git a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs index 8252b5d0..140dac2d 100644 --- a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs +++ b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs @@ -2,10 +2,10 @@ use pagetop::prelude::*; #[derive(Iden)] enum NodeAccess { - Table, // Identifies which realm/grant pairs a user must possess in order to view, - // update, or delete specific nodes. + Table, // node_access: Identifies which realm/grant pairs a user must possess in + // order to view, update, or delete specific nodes. - Nid, // The {node}.nid this record affects. + Nid, // The Node.nid this record affects. Gid, // The grant ID a user must possess in the specified realm to gain this // row's privileges on the node. Realm, // The realm in which the user must possess the grant ID. Each node access diff --git a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs index 9c414a60..0009359f 100644 --- a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs +++ b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs @@ -2,11 +2,11 @@ use pagetop::prelude::*; #[derive(Iden)] enum NodeRevision { - Table, // Stores information about each saved version of a {node}. + Table, // node_revision: Stores information about each saved version of a Node. - Nid, // The {node} this version belongs to. + Nid, // The Node this version belongs to. Vid, // The primary identifier for this version. - Uid, // The {users}.uid that created this version. + Uid, // The User.uid that created this version. Title, // The title of this version. Log, // The log entry explaining the changes in this version. Timestamp, // A Unix timestamp indicating when this version was created. diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs index 61d21372..2557453f 100644 --- a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs +++ b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs @@ -2,7 +2,7 @@ use pagetop::prelude::*; #[derive(Iden)] enum Role { - Table, // Store user roles. + Table, // role: Store user roles. Rid, // Primary Key: Unique role ID. Name, // Unique role name. @@ -31,23 +31,25 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Role::Weight) .integer() .not_null() - .default(0) + .default(10) ) // INDEXES. .index(Index::create() - .name("name-weight") - .col(Role::Name) + .name("weight-name") .col(Role::Weight) + .col(Role::Name) ) .to_owned() ) .await?; + // Built-in roles. app::db::exec::(Query::insert() .into_table(Role::Table) - .columns(vec![Role::Name]) - .values_panic(vec!["anonymous".into()]) - .values_panic(vec!["authenticated".into()]) + .columns(vec![Role::Name, Role::Weight]) + .values_panic(vec!["anonymous".into(), "1".into()]) + .values_panic(vec!["authenticated".into(), "2".into()]) + .values_panic(vec!["administrator".into(), "3".into()]) ) .await.map(|_| ()) } diff --git a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs index d5e5f8f1..052fed2c 100644 --- a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs +++ b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs @@ -2,11 +2,10 @@ use pagetop::prelude::*; #[derive(Iden)] enum RolePermission { - Table, // Stores the permissions assigned to user roles. + Table, // role_permission: Stores the permissions assigned to user roles. Rid, // Foreign Key: Role::Rid. Permission, // A single permission granted to the role identified by Rid. - Module, // The module declaring the permission. } #[derive(Iden)] @@ -28,10 +27,6 @@ impl MigrationTrait for Migration { .string_len(128) .not_null() ) - .col(ColumnDef::new(RolePermission::Module) - .string_len(255) - .not_null() - ) // INDEXES. .primary_key(Index::create() .col(RolePermission::Rid) @@ -45,8 +40,8 @@ impl MigrationTrait for Migration { .name("fk_role_permission-rid") .from(RolePermission::Table, RolePermission::Rid) .to(Role::Table, Role::Rid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Restrict) + .on_update(ForeignKeyAction::Restrict) ) .to_owned() ) diff --git a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs index 4849eae5..c060c8a5 100644 --- a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs +++ b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs @@ -2,7 +2,7 @@ use pagetop::prelude::*; #[derive(Iden)] enum User { - Table, // Stores user data. + Table, // user: Stores user data. Uid, // Primary Key: Unique user ID. Name, // Unique user name. diff --git a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs index 1b15810c..fedcd4be 100644 --- a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs +++ b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs @@ -2,7 +2,7 @@ use pagetop::prelude::*; #[derive(Iden)] enum UserRole { - Table, // Maps users to roles. + Table, // user_role: Maps users to roles. Uid, // Foreign Key: User::Uid for user. Rid, // Foreign Key: Role::Rid for role. @@ -39,15 +39,15 @@ impl MigrationTrait for Migration { .name("fk_user_role-uid") .from(UserRole::Table, UserRole::Uid) .to(User::Table, User::Uid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Restrict) + .on_update(ForeignKeyAction::Restrict) ) .foreign_key(ForeignKey::create() .name("fk_user_role-rid") .from(UserRole::Table, UserRole::Rid) .to(Role::Table, Role::Rid) - .on_delete(ForeignKeyAction::Cascade) - .on_update(ForeignKeyAction::Cascade) + .on_delete(ForeignKeyAction::Restrict) + .on_update(ForeignKeyAction::Restrict) ) .to_owned() ) From cd7020c77d5aafe78861db2f7fc1b66ca920c3de Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 29 Apr 2022 20:06:44 +0200 Subject: [PATCH 35/80] =?UTF-8?q?A=C3=B1ade=20func.=20component=5Fxxx()?= =?UTF-8?q?=20para=20capturar=20comp.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/block.rs | 2 +- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 2 +- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 2 +- pagetop/src/base/component/grid/column.rs | 2 +- pagetop/src/base/component/grid/row.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 4 ++-- pagetop/src/base/theme/bulmix/mod.rs | 4 ++-- pagetop/src/response/page/component.rs | 10 +++++++++- pagetop/src/response/page/mod.rs | 7 ++++++- pagetop/src/theme/definition.rs | 4 ++-- 16 files changed, 32 insertions(+), 19 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 727ff86e..881a4ac5 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -46,7 +46,7 @@ impl PageComponent for Block { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index e0613d3b..3fa5db9e 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -29,7 +29,7 @@ impl PageComponent for Chunck { html! { (*self.html()) } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 86e907a9..8e53c8b2 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -73,7 +73,7 @@ impl PageComponent for Container { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 7f7ada99..ff7c7ef4 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -66,7 +66,7 @@ impl PageComponent for Button { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index a062630d..f24f2bc2 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -85,7 +85,7 @@ impl PageComponent for Date { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 0470436f..05d6296c 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -55,7 +55,7 @@ impl PageComponent for Form { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 6e3edecc..ae19cf0b 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -29,7 +29,7 @@ impl PageComponent for Hidden { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 01158ac5..08318bd3 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -113,7 +113,7 @@ impl PageComponent for Input { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 59948416..d48da98d 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -41,7 +41,7 @@ impl PageComponent for Column { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 15b87cef..761fdb49 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -41,7 +41,7 @@ impl PageComponent for Row { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 0b4b4168..c785f099 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -38,7 +38,7 @@ impl PageComponent for Image { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index e5fb46cf..805f4dbb 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -68,7 +68,7 @@ impl PageComponent for MenuItem { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } @@ -226,7 +226,7 @@ impl PageComponent for Menu { } } - fn as_any(&self) -> &dyn AnyComponent { + fn as_ref_any(&self) -> &dyn AnyComponent { self } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 340b8c35..22a03efe 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -39,11 +39,11 @@ impl ThemeTrait for BulmixTheme { ) { match component.name() { "GridRow" => { - let row = component.as_mut_any().downcast_mut::().unwrap(); + let row = component_mut::(component); row.alter_classes("columns", ClassesOp::SetDefault); }, "GridColumn" => { - let col = component.as_mut_any().downcast_mut::().unwrap(); + let col = component_mut::(component); col.alter_classes("column", ClassesOp::SetDefault); }, _ => {}, diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index e4d6b61c..de726704 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -42,7 +42,15 @@ pub trait PageComponent: AnyComponent + Send + Sync { html! {} } - fn as_any(&self) -> &dyn AnyComponent; + fn as_ref_any(&self) -> &dyn AnyComponent; fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } + +pub fn component_ref(component: &dyn PageComponent) -> &T { + component.as_ref_any().downcast_ref::().unwrap() +} + +pub fn component_mut(component: &mut dyn PageComponent) -> &mut T { + component.as_mut_any().downcast_mut::().unwrap() +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index e238954b..5f0bf0e6 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -7,7 +7,12 @@ pub use assets::{ }; mod component; -pub use component::{AnyComponent, PageComponent}; +pub use component::{ + AnyComponent, + PageComponent, + component_ref, + component_mut, +}; mod container; pub use container::PageContainer; diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 29b20d4c..41113639 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -85,7 +85,7 @@ pub trait ThemeTrait: Send + Sync { match component.name() { "Block" => { - let block = component.as_mut_any().downcast_mut::().unwrap(); + let block = component_mut::(component); block.alter_title("New title"); }, _ => {}, @@ -105,7 +105,7 @@ pub trait ThemeTrait: Send + Sync { match component.name() { "Block" => { - let block = component.as_any().downcast_ref::().unwrap(); + let block = component_ref::(component); match block.template() { "default" => Some(block_default(block)), _ => None, From 37d0254055a5366466db14b0fd46f76f97810d82 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 30 Apr 2022 09:46:03 +0200 Subject: [PATCH 36/80] Modifica PageComponent por ComponentTrait --- pagetop/src/base/component/block.rs | 4 ++-- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 4 ++-- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 4 ++-- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 2 +- pagetop/src/base/component/grid/column.rs | 4 ++-- pagetop/src/base/component/grid/row.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 4 ++-- pagetop/src/base/theme/bulmix/mod.rs | 2 +- pagetop/src/response/page/component.rs | 6 +++--- pagetop/src/response/page/container.rs | 8 ++++---- pagetop/src/response/page/mod.rs | 2 +- pagetop/src/response/page/page.rs | 6 +++--- pagetop/src/theme/definition.rs | 6 +++--- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 881a4ac5..7f125eb5 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -10,7 +10,7 @@ pub struct Block { template : String, } -impl PageComponent for Block { +impl ComponentTrait for Block { fn new() -> Self { Block { renderable: render_always, @@ -59,7 +59,7 @@ impl Block { // Block CONTAINER. - pub fn add(mut self, component: impl PageComponent) -> Self { + pub fn add(mut self, component: impl ComponentTrait) -> Self { self.components.add(component); self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 3fa5db9e..1abd7554 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -7,7 +7,7 @@ pub struct Chunck { template : String, } -impl PageComponent for Chunck { +impl ComponentTrait for Chunck { fn new() -> Self { Chunck { renderable: render_always, diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 8e53c8b2..72766ac8 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -13,7 +13,7 @@ pub struct Container { template : String, } -impl PageComponent for Container { +impl ComponentTrait for Container { fn new() -> Self { Container { renderable : render_always, @@ -109,7 +109,7 @@ impl Container { // Container CONTAINER. - pub fn add(mut self, component: impl PageComponent) -> Self { + pub fn add(mut self, component: impl ComponentTrait) -> Self { self.components.add(component); self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index ff7c7ef4..74f0ba2f 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -14,7 +14,7 @@ pub struct Button { template : String, } -impl PageComponent for Button { +impl ComponentTrait for Button { fn new() -> Self { Button { renderable : render_always, diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index f24f2bc2..f0c0cd33 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -17,7 +17,7 @@ pub struct Date { template : String, } -impl PageComponent for Date { +impl ComponentTrait for Date { fn new() -> Self { Date { renderable : render_always, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 05d6296c..79fc72dd 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -14,7 +14,7 @@ pub struct Form { template : String, } -impl PageComponent for Form { +impl ComponentTrait for Form { fn new() -> Self { Form { renderable: render_always, @@ -68,7 +68,7 @@ impl Form { // Form CONTAINER. - pub fn add(mut self, element: impl PageComponent) -> Self { + pub fn add(mut self, element: impl ComponentTrait) -> Self { self.elements.add(element); self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index ae19cf0b..baa0316f 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -6,7 +6,7 @@ pub struct Hidden { value : OptAttr, } -impl PageComponent for Hidden { +impl ComponentTrait for Hidden { fn new() -> Self { Hidden { weight: 0, diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 08318bd3..f682ad3d 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -23,7 +23,7 @@ pub struct Input { template : String, } -impl PageComponent for Input { +impl ComponentTrait for Input { fn new() -> Self { Input { renderable : render_always, diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index d48da98d..f80d0ff3 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -9,7 +9,7 @@ pub struct Column { template : String, } -impl PageComponent for Column { +impl ComponentTrait for Column { fn new() -> Self { Column { renderable: render_always, @@ -54,7 +54,7 @@ impl Column { // Column CONTAINER. - pub fn add(mut self, component: impl PageComponent) -> Self { + pub fn add(mut self, component: impl ComponentTrait) -> Self { self.components.add(component); self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 761fdb49..273701ed 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -9,7 +9,7 @@ pub struct Row { template : String, } -impl PageComponent for Row { +impl ComponentTrait for Row { fn new() -> Self { Row { renderable: render_always, diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index c785f099..de1d6840 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -9,7 +9,7 @@ pub struct Image { template : String, } -impl PageComponent for Image { +impl ComponentTrait for Image { fn new() -> Self { Image { renderable: render_always, diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 805f4dbb..5fb9f1cc 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -20,7 +20,7 @@ pub struct MenuItem { item_type : MenuItemType, } -impl PageComponent for MenuItem { +impl ComponentTrait for MenuItem { fn new() -> Self { MenuItem { renderable: render_always, @@ -179,7 +179,7 @@ pub struct Menu { template : String, } -impl PageComponent for Menu { +impl ComponentTrait for Menu { fn new() -> Self { Menu { renderable: render_always, diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 22a03efe..7454c69d 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -34,7 +34,7 @@ impl ThemeTrait for BulmixTheme { fn before_render_component( &self, - component: &mut dyn PageComponent, + component: &mut dyn ComponentTrait, _assets: &mut PageAssets ) { match component.name() { diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index de726704..8839a5ca 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -5,7 +5,7 @@ use std::any::type_name; pub use std::any::Any as AnyComponent; -pub trait PageComponent: AnyComponent + Send + Sync { +pub trait ComponentTrait: AnyComponent + Send + Sync { fn new() -> Self where Self: Sized; @@ -47,10 +47,10 @@ pub trait PageComponent: AnyComponent + Send + Sync { fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } -pub fn component_ref(component: &dyn PageComponent) -> &T { +pub fn component_ref(component: &dyn ComponentTrait) -> &T { component.as_ref_any().downcast_ref::().unwrap() } -pub fn component_mut(component: &mut dyn PageComponent) -> &mut T { +pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut T { component.as_mut_any().downcast_mut::().unwrap() } diff --git a/pagetop/src/response/page/container.rs b/pagetop/src/response/page/container.rs index 2e052ee9..6cf09607 100644 --- a/pagetop/src/response/page/container.rs +++ b/pagetop/src/response/page/container.rs @@ -1,23 +1,23 @@ use crate::html::{Markup, html}; -use crate::response::page::{PageAssets, PageComponent, render_component}; +use crate::response::page::{PageAssets, ComponentTrait, render_component}; use std::sync::{Arc, RwLock}; #[derive(Clone)] -pub struct PageContainer(Vec>>); +pub struct PageContainer(Vec>>); impl PageContainer { pub fn new() -> Self { PageContainer(Vec::new()) } - pub fn new_with(component: impl PageComponent) -> Self { + pub fn new_with(component: impl ComponentTrait) -> Self { let mut container = PageContainer::new(); container.add(component); container } - pub fn add(&mut self, component: impl PageComponent) { + pub fn add(&mut self, component: impl ComponentTrait) { self.0.push(Arc::new(RwLock::new(component))); } diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 5f0bf0e6..1d923f73 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -9,7 +9,7 @@ pub use assets::{ mod component; pub use component::{ AnyComponent, - PageComponent, + ComponentTrait, component_ref, component_mut, }; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index f7bee609..2a1f69f4 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -100,7 +100,7 @@ impl<'a> Page<'a> { pub fn add_to( &mut self, region: &'a str, - component: impl PageComponent + component: impl ComponentTrait ) -> &mut Self { if let Some(regions) = self.regions.get_mut(region) { regions.add(component); @@ -187,7 +187,7 @@ impl<'a> Page<'a> { } } -pub fn render_component(component: &mut dyn PageComponent, assets: &mut PageAssets) -> Markup { +pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut PageAssets) -> Markup { component.before_render(assets); assets.theme().before_render_component(component, assets); match component.is_renderable() { @@ -201,7 +201,7 @@ pub fn render_component(component: &mut dyn PageComponent, assets: &mut PageAsse } } -pub fn add_component_to(region: &'static str, component: impl PageComponent) { +pub fn add_component_to(region: &'static str, component: impl ComponentTrait) { let mut hmap = COMPONENTS.write().unwrap(); if let Some(regions) = hmap.get_mut(region) { regions.add(component); diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 41113639..4d54d758 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -1,7 +1,7 @@ use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::response::page::{Favicon, Page, PageAssets, PageComponent}; +use crate::response::page::{ComponentTrait, Favicon, Page, PageAssets}; use crate::base::component::Chunck; /// Los temas deben implementar este "trait". @@ -77,7 +77,7 @@ pub trait ThemeTrait: Send + Sync { #[allow(unused_variables)] fn before_render_component( &self, - component: &mut dyn PageComponent, + component: &mut dyn ComponentTrait, assets: &mut PageAssets ) { /* @@ -96,7 +96,7 @@ pub trait ThemeTrait: Send + Sync { #[allow(unused_variables)] fn render_component( &self, - component: &dyn PageComponent, + component: &dyn ComponentTrait, assets: &mut PageAssets ) -> Option { None From 16996eeee0986725aeea1ed83d46db0cff16d458 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 2 May 2022 12:29:06 +0200 Subject: [PATCH 37/80] =?UTF-8?q?A=C3=B1ade=20y=20estandariza=20nombres=20?= =?UTF-8?q?de=20m=C3=B3d.,=20tem.=20y=20comp.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/module/all.rs | 2 +- pagetop/src/module/definition.rs | 37 ++++++++++++++++---- pagetop/src/module/mod.rs | 5 ++- pagetop/src/response/page/component.rs | 47 ++++++++++++++++---------- pagetop/src/response/page/mod.rs | 1 + pagetop/src/theme/all.rs | 2 +- pagetop/src/theme/definition.rs | 31 ++++++++++++++--- pagetop/src/theme/mod.rs | 5 ++- pagetop/src/util.rs | 11 ++++++ 9 files changed, 109 insertions(+), 32 deletions(-) diff --git a/pagetop/src/module/all.rs b/pagetop/src/module/all.rs index 6380917a..2e499f23 100644 --- a/pagetop/src/module/all.rs +++ b/pagetop/src/module/all.rs @@ -19,7 +19,7 @@ pub fn register_module(module: &'static dyn ModuleTrait) { fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { if !MODULES.read().unwrap().iter().any(|m| m.name() == module.name()) { if !list.iter().any(|m| m.name() == module.name()) { - trace::debug!("Registering \"{}\" module", module.name()); + trace::debug!("Registering \"{}\" module", module.single_name()); list.push(module); let mut dependencies = module.dependencies(); diff --git a/pagetop/src/module/definition.rs b/pagetop/src/module/definition.rs index a3affa2f..baaadd98 100644 --- a/pagetop/src/module/definition.rs +++ b/pagetop/src/module/definition.rs @@ -1,22 +1,31 @@ use crate::app; +use crate::util::partial_type_name; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; +pub trait BaseModule { + fn type_name(&self) -> &'static str; + + fn single_name(&self) -> &'static str; + + fn qualified_name(&self, last: usize) -> &'static str; +} + /// Los módulos deben implementar este *trait*. -pub trait ModuleTrait: Send + Sync { - fn name(&self) -> &'static str; - - fn fullname(&self) -> String; - - fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { - vec![] +pub trait ModuleTrait: BaseModule + Send + Sync { + fn name(&self) -> String { + self.single_name().to_owned() } fn description(&self) -> Option { None } + fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } + #[allow(unused_variables)] fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { } @@ -27,3 +36,17 @@ pub trait ModuleTrait: Send + Sync { vec![] } } + +impl BaseModule for M { + fn type_name(&self) -> &'static str { + std::any::type_name::() + } + + fn single_name(&self) -> &'static str { + partial_type_name(std::any::type_name::(), 1) + } + + fn qualified_name(&self, last: usize) -> &'static str { + partial_type_name(std::any::type_name::(), last) + } +} diff --git a/pagetop/src/module/mod.rs b/pagetop/src/module/mod.rs index a767683b..720d806c 100644 --- a/pagetop/src/module/mod.rs +++ b/pagetop/src/module/mod.rs @@ -1,5 +1,8 @@ mod definition; -pub use definition::ModuleTrait; +pub use definition::{ + BaseModule, + ModuleTrait, +}; pub(crate) mod all; pub use all::register_module; \ No newline at end of file diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/response/page/component.rs index 8839a5ca..a423707f 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/response/page/component.rs @@ -1,24 +1,23 @@ use crate::html::{Markup, html}; use crate::response::page::PageAssets; - -use std::any::type_name; +use crate::util::partial_type_name; pub use std::any::Any as AnyComponent; -pub trait ComponentTrait: AnyComponent + Send + Sync { +pub trait BaseComponent { + fn type_name(&self) -> &'static str; + + fn single_name(&self) -> &'static str; + + fn qualified_name(&self, last: usize) -> &'static str; +} + +pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { fn new() -> Self where Self: Sized; - fn name(&self) -> &'static str { - let name = type_name::(); - match name.rfind("::") { - Some(position) => &name[(position + 2)..], - None => name - } - } - - fn fullname(&self) -> String { - type_name::().to_owned() + fn name(&self) -> String { + self.single_name().to_owned() } fn description(&self) -> Option { @@ -47,10 +46,24 @@ pub trait ComponentTrait: AnyComponent + Send + Sync { fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } -pub fn component_ref(component: &dyn ComponentTrait) -> &T { - component.as_ref_any().downcast_ref::().unwrap() +impl BaseComponent for C { + fn type_name(&self) -> &'static str { + std::any::type_name::() + } + + fn single_name(&self) -> &'static str { + partial_type_name(std::any::type_name::(), 1) + } + + fn qualified_name(&self, last: usize) -> &'static str { + partial_type_name(std::any::type_name::(), last) + } } -pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut T { - component.as_mut_any().downcast_mut::().unwrap() +pub fn component_ref(component: &dyn ComponentTrait) -> &C { + component.as_ref_any().downcast_ref::().unwrap() +} + +pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { + component.as_mut_any().downcast_mut::().unwrap() } diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 1d923f73..01add24f 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -9,6 +9,7 @@ pub use assets::{ mod component; pub use component::{ AnyComponent, + BaseComponent, ComponentTrait, component_ref, component_mut, diff --git a/pagetop/src/theme/all.rs b/pagetop/src/theme/all.rs index ee0bfedb..12d96338 100644 --- a/pagetop/src/theme/all.rs +++ b/pagetop/src/theme/all.rs @@ -13,7 +13,7 @@ static THEMES: Lazy>> = Lazy::new(|| { pub fn register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); if !themes.iter().any(|t| t.name() == theme.name()) { - trace::debug!("Registering \"{}\" theme", theme.name()); + trace::debug!("Registering \"{}\" theme", theme.single_name()); themes.push(theme); } } diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/theme/definition.rs index 4d54d758..ef21491a 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/theme/definition.rs @@ -3,12 +3,21 @@ use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::response::page::{ComponentTrait, Favicon, Page, PageAssets}; use crate::base::component::Chunck; +use crate::util::partial_type_name; + +pub trait BaseTheme { + fn type_name(&self) -> &'static str; + + fn single_name(&self) -> &'static str; + + fn qualified_name(&self, last: usize) -> &'static str; +} /// Los temas deben implementar este "trait". -pub trait ThemeTrait: Send + Sync { - fn name(&self) -> &'static str; - - fn fullname(&self) -> String; +pub trait ThemeTrait: BaseTheme + Send + Sync { + fn name(&self) -> String { + self.single_name().to_owned() + } fn description(&self) -> Option { None @@ -127,3 +136,17 @@ pub trait ThemeTrait: Send + Sync { .render() } } + +impl BaseTheme for T { + fn type_name(&self) -> &'static str { + std::any::type_name::() + } + + fn single_name(&self) -> &'static str { + partial_type_name(std::any::type_name::(), 1) + } + + fn qualified_name(&self, last: usize) -> &'static str { + partial_type_name(std::any::type_name::(), last) + } +} diff --git a/pagetop/src/theme/mod.rs b/pagetop/src/theme/mod.rs index 4456189e..f76d1fe3 100644 --- a/pagetop/src/theme/mod.rs +++ b/pagetop/src/theme/mod.rs @@ -1,5 +1,8 @@ mod definition; -pub use definition::ThemeTrait; +pub use definition::{ + BaseTheme, + ThemeTrait, +}; pub(crate) mod all; pub use all::{ diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index 02bb584e..ca4a96fc 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -46,3 +46,14 @@ macro_rules! theme_static_files { } }}; } + +pub(crate) fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { + if last == 0 { + return type_name; + } + let positions: Vec<_> = type_name.rmatch_indices("::").collect(); + if positions.len() < last { + return type_name; + } + &type_name[(positions[last - 1].0 + 2)..] +} From a8cb7f0d29b75212bb31edaddc51ad40b181242c Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 2 May 2022 12:30:30 +0200 Subject: [PATCH 38/80] =?UTF-8?q?Actualiza=20el=20c=C3=B3digo=20para=20las?= =?UTF-8?q?=20nuevas=20denominaciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drust/src/main.rs | 6 ++--- pagetop-admin/src/lib.rs | 12 ++++------ pagetop-admin/src/locales/en-US/admin.ftl | 2 +- pagetop-admin/src/locales/es-ES/admin.ftl | 2 +- pagetop-admin/src/summary.rs | 2 +- pagetop-node/src/lib.rs | 12 ++++------ pagetop-node/src/locales/en-US/homepage.ftl | 2 +- pagetop-node/src/locales/es-ES/homepage.ftl | 2 +- pagetop-user/src/lib.rs | 12 ++++------ pagetop-user/src/locales/en-US/homepage.ftl | 2 +- pagetop-user/src/locales/es-ES/homepage.ftl | 2 +- pagetop/src/app/application.rs | 10 ++++---- pagetop/src/base/component/block.rs | 4 +++- pagetop/src/base/component/chunck.rs | 2 ++ pagetop/src/base/component/container.rs | 2 ++ pagetop/src/base/component/form/button.rs | 2 ++ pagetop/src/base/component/form/date.rs | 2 ++ pagetop/src/base/component/form/form.rs | 2 ++ pagetop/src/base/component/form/hidden.rs | 2 ++ pagetop/src/base/component/form/input.rs | 2 ++ pagetop/src/base/component/form/mod.rs | 20 ++++++++++++---- pagetop/src/base/component/grid/column.rs | 6 ++--- pagetop/src/base/component/grid/mod.rs | 8 +++++-- pagetop/src/base/component/grid/row.rs | 6 ++--- pagetop/src/base/component/image.rs | 2 ++ pagetop/src/base/component/menu.rs | 9 ++++--- pagetop/src/base/component/mod.rs | 24 ++++++++++++++----- pagetop/src/base/mod.rs | 2 +- .../demopage/locales/en-US/demopage.ftl | 2 +- .../demopage/locales/es-ES/demopage.ftl | 2 +- pagetop/src/base/module/demopage/mod.rs | 12 ++++------ pagetop/src/base/theme/aliner/mod.rs | 12 ++-------- pagetop/src/base/theme/bootsier/mod.rs | 12 ++-------- pagetop/src/base/theme/bulmix/mod.rs | 18 ++++---------- pagetop/src/base/theme/minimal/mod.rs | 11 ++------- pagetop/src/lib.rs | 20 ++++++++-------- pagetop/src/prelude.rs | 2 +- pagetop/src/response/page/assets.rs | 10 +------- 38 files changed, 123 insertions(+), 139 deletions(-) diff --git a/drust/src/main.rs b/drust/src/main.rs index e51f5311..9da7b124 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,9 +1,9 @@ use pagetop::prelude::*; fn bootstrap() { - register_module(&pagetop_admin::AdminModule); - register_module(&pagetop_user::UserModule); - register_module(&pagetop_node::NodeModule); + register_module(&pagetop_admin::Admin); + register_module(&pagetop_user::User); + register_module(&pagetop_node::Node); } #[actix_web::main] diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index a00e7fae..c07f617b 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -4,15 +4,11 @@ localize!("src/locales"); mod summary; -pub struct AdminModule; +pub struct Admin; -impl ModuleTrait for AdminModule { - fn name(&self) -> &'static str { - "Admin" - } - - fn fullname(&self) -> String { - l("module_fullname") +impl ModuleTrait for Admin { + fn name(&self) -> String { + l("module_name") } fn description(&self) -> Option { diff --git a/pagetop-admin/src/locales/en-US/admin.ftl b/pagetop-admin/src/locales/en-US/admin.ftl index 88da2fe6..758f5ab5 100644 --- a/pagetop-admin/src/locales/en-US/admin.ftl +++ b/pagetop-admin/src/locales/en-US/admin.ftl @@ -1,2 +1,2 @@ -module_fullname = Admin module +module_name = Admin module module_description = Administration module. diff --git a/pagetop-admin/src/locales/es-ES/admin.ftl b/pagetop-admin/src/locales/es-ES/admin.ftl index c9105a6a..ba596691 100644 --- a/pagetop-admin/src/locales/es-ES/admin.ftl +++ b/pagetop-admin/src/locales/es-ES/admin.ftl @@ -1,2 +1,2 @@ -module_fullname = Admin module +module_name = Admin module module_description = Módulo de administración. diff --git a/pagetop-admin/src/summary.rs b/pagetop-admin/src/summary.rs index b91b97fa..696f408d 100644 --- a/pagetop-admin/src/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -3,7 +3,7 @@ use super::l; pub async fn summary() -> app::Result { let top_menu = Menu::new() - .add(MenuItem::label(l("module_fullname").as_str())) + .add(MenuItem::label(l("module_name").as_str())) .add(MenuItem::link("Opción 2", "https://www.google.es")) .add(MenuItem::link_blank("Opción 3", "https://www.google.es")) .add(MenuItem::submenu("Submenú 1", Menu::new() diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index a05800ec..c9e2dcda 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -5,15 +5,11 @@ localize!("src/locales"); //mod entity; mod migration; -pub struct NodeModule; +pub struct Node; -impl ModuleTrait for NodeModule { - fn name(&self) -> &'static str { - "Node" - } - - fn fullname(&self) -> String { - l("module_fullname") +impl ModuleTrait for Node { + fn name(&self) -> String { + l("module_name") } fn description(&self) -> Option { diff --git a/pagetop-node/src/locales/en-US/homepage.ftl b/pagetop-node/src/locales/en-US/homepage.ftl index 191dc81f..46a2e750 100644 --- a/pagetop-node/src/locales/en-US/homepage.ftl +++ b/pagetop-node/src/locales/en-US/homepage.ftl @@ -1,2 +1,2 @@ -module_fullname = Node +module_name = Node module_description = Allows content to be submitted to the site and displayed on pages. diff --git a/pagetop-node/src/locales/es-ES/homepage.ftl b/pagetop-node/src/locales/es-ES/homepage.ftl index b5e6677d..a2253fe9 100644 --- a/pagetop-node/src/locales/es-ES/homepage.ftl +++ b/pagetop-node/src/locales/es-ES/homepage.ftl @@ -1,2 +1,2 @@ -module_fullname = Nodo +module_name = Nodo module_description = Permite enviar contenidos al sitio y mostrarlos en páginas. diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index d5d96f37..bbbf01f3 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -4,15 +4,11 @@ localize!("src/locales"); mod migration; -pub struct UserModule; +pub struct User; -impl ModuleTrait for UserModule { - fn name(&self) -> &'static str { - "User" - } - - fn fullname(&self) -> String { - l("module_fullname") +impl ModuleTrait for User { + fn name(&self) -> String { + l("module_name") } fn description(&self) -> Option { diff --git a/pagetop-user/src/locales/en-US/homepage.ftl b/pagetop-user/src/locales/en-US/homepage.ftl index 0493672e..710369d7 100644 --- a/pagetop-user/src/locales/en-US/homepage.ftl +++ b/pagetop-user/src/locales/en-US/homepage.ftl @@ -1,4 +1,4 @@ -module_fullname = User +module_name = User module_description = Manages the user registration and login system. username = User name diff --git a/pagetop-user/src/locales/es-ES/homepage.ftl b/pagetop-user/src/locales/es-ES/homepage.ftl index f5f6e1bb..8faaf12d 100644 --- a/pagetop-user/src/locales/es-ES/homepage.ftl +++ b/pagetop-user/src/locales/es-ES/homepage.ftl @@ -1,4 +1,4 @@ -module_fullname = Usuario +module_name = Usuario module_description = Gestiona el registro de usuarios y el sistema de accesos. username = Nombre de usuario diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index f0473180..f183bbfc 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -28,10 +28,10 @@ impl Application { Lazy::force(&app::db::DBCONN); // Registra los temas predeterminados. - theme::register_theme(&base::theme::aliner::AlinerTheme); - theme::register_theme(&base::theme::minimal::MinimalTheme); - theme::register_theme(&base::theme::bootsier::BootsierTheme); - theme::register_theme(&base::theme::bulmix::BulmixTheme); + theme::register_theme(&base::theme::aliner::Aliner); + theme::register_theme(&base::theme::minimal::Minimal); + theme::register_theme(&base::theme::bootsier::Bootsier); + theme::register_theme(&base::theme::bulmix::Bulmix); // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); @@ -39,7 +39,7 @@ impl Application { // Registra el módulo de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. - module::register_module(&base::module::demopage::DemopageModule); + module::register_module(&base::module::demopage::Demopage); // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 7f125eb5..96dc06b6 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_BLOCK: &str = "pagetop::base::component::block::Block"; + pub struct Block { renderable: fn() -> bool, weight : i8, @@ -32,7 +34,7 @@ impl ComponentTrait for Block { } fn default_render(&self, assets: &mut PageAssets) -> Markup { - let id = assets.serial_id(self.name(), self.id()); + let id = assets.serial_id(self.single_name(), self.id()); html! { div id=(id) class=[self.classes()] { @match self.title() { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 1abd7554..902b1eef 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_CHUNCK: &str = "pagetop::base::component::chunck::Chunck"; + pub struct Chunck { renderable: fn() -> bool, weight : i8, diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 72766ac8..2bfbc3e0 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_CONTAINER: &str = "pagetop::base::component::container::Container"; + pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 74f0ba2f..783adbc6 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_BUTTON: &str = "pagetop::base::component::form::button::Button"; + pub enum ButtonType {Button, Reset, Submit} pub struct Button { diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index f0c0cd33..7ef3f82d 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_DATE: &str = "pagetop::base::component::form::date::Date"; + pub struct Date { renderable : fn() -> bool, weight : i8, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 79fc72dd..e6b10261 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_FORM: &str = "pagetop::base::component::form::form::Form"; + pub enum FormMethod {Get, Post} pub struct Form { diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index baa0316f..3e9b41f3 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_HIDDEN: &str = "pagetop::base::component::form::hidden::Hidden"; + pub struct Hidden { weight: i8, name : OptIden, diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index f682ad3d..7a45ce21 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_INPUT: &str = "pagetop::base::component::form::input::Input"; + pub enum InputType {Email, Password, Search, Telephone, Textfield, Url} pub struct Input { diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/base/component/form/mod.rs index 23b965e9..d8df6d2d 100644 --- a/pagetop/src/base/component/form/mod.rs +++ b/pagetop/src/base/component/form/mod.rs @@ -1,11 +1,21 @@ mod form; -pub use form::{Form, FormMethod}; +pub use form::{ + TYPENAME_FORM, Form, FormMethod +}; mod input; -pub use input::{Input, InputType}; +pub use input::{ + TYPENAME_INPUT, Input, InputType +}; mod hidden; -pub use hidden::Hidden; +pub use hidden::{ + TYPENAME_HIDDEN, Hidden +}; mod date; -pub use date::Date; +pub use date::{ + TYPENAME_DATE, Date +}; mod button; -pub use button::{Button, ButtonType}; +pub use button::{ + TYPENAME_BUTTON, Button, ButtonType +}; diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index f80d0ff3..b4121549 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_COLUMN: &str = "pagetop::base::component::grid::column::Column"; + pub struct Column { renderable: fn() -> bool, weight : i8, @@ -21,10 +23,6 @@ impl ComponentTrait for Column { } } - fn name(&self) -> &'static str { - "GridColumn" - } - fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/grid/mod.rs b/pagetop/src/base/component/grid/mod.rs index ca7796ef..e63ea7cd 100644 --- a/pagetop/src/base/component/grid/mod.rs +++ b/pagetop/src/base/component/grid/mod.rs @@ -1,4 +1,8 @@ mod row; -pub use row::Row; +pub use row::{ + TYPENAME_ROW, Row +}; mod column; -pub use column::Column; +pub use column::{ + TYPENAME_COLUMN, Column +}; diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 273701ed..8077fec6 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_ROW: &str = "pagetop::base::component::grid::row::Row"; + pub struct Row { renderable: fn() -> bool, weight : i8, @@ -21,10 +23,6 @@ impl ComponentTrait for Row { } } - fn name(&self) -> &'static str { - "GridRow" - } - fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index de1d6840..b88ead07 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const TYPENAME_IMAGE: &str = "pagetop::base::component::image::Image"; + pub struct Image { renderable: fn() -> bool, weight : i8, diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 5fb9f1cc..845284f9 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,5 +1,8 @@ use crate::prelude::*; +pub const TYPENAME_MENU: &str = "pagetop::base::component::menu::Menu"; +pub const TYPENAME_MENUITEM: &str = "pagetop::base::component::menu::MenuItem"; + pub enum MenuItemType { Label(String), Link(String, String), @@ -10,9 +13,7 @@ pub enum MenuItemType { Void, } -// ----------------------------------------------------------------------------- // MenuItem. -// ----------------------------------------------------------------------------- pub struct MenuItem { renderable: fn() -> bool, @@ -166,9 +167,7 @@ impl MenuItem { } } -// ----------------------------------------------------------------------------- // Menu. -// ----------------------------------------------------------------------------- pub struct Menu { renderable: fn() -> bool, @@ -212,7 +211,7 @@ impl ComponentTrait for Menu { )) .add_jquery(); - let id = assets.serial_id(self.name(), self.id()); + let id = assets.serial_id(self.single_name(), self.id()); html! { ul id=(id) class=[self.classes()] { (self.items().render(assets)) diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index b4e646b9..032fd625 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -1,16 +1,28 @@ mod container; -pub use container::{Container, ContainerType}; +pub use container::{ + TYPENAME_CONTAINER, Container, ContainerType +}; pub mod grid; mod chunck; -pub use chunck::Chunck; +pub use chunck::{ + TYPENAME_CHUNCK, Chunck +}; mod block; -pub use block::Block; +pub use block::{ + TYPENAME_BLOCK, Block +}; mod image; -pub use image::Image; +pub use image::{ + TYPENAME_IMAGE, Image +}; mod menu; -pub use menu::{Menu, MenuItem, MenuItemType}; +pub use menu::{ + TYPENAME_MENU, TYPENAME_MENUITEM, Menu, MenuItem, MenuItemType +}; pub mod form; -pub use form::{Form, FormMethod}; +pub use form::{ + TYPENAME_FORM, Form, FormMethod +}; diff --git a/pagetop/src/base/mod.rs b/pagetop/src/base/mod.rs index 6a8ebdf7..d58aa565 100644 --- a/pagetop/src/base/mod.rs +++ b/pagetop/src/base/mod.rs @@ -1,3 +1,3 @@ pub mod component; pub mod module; -pub mod theme; \ No newline at end of file +pub mod theme; diff --git a/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl index d23f6ce6..27749979 100644 --- a/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl +++ b/pagetop/src/base/module/demopage/locales/en-US/demopage.ftl @@ -1,4 +1,4 @@ -module_fullname = Default homepage +module_name = Default homepage module_description = Displays a demo homepage when none is configured. page_title = Hello world! diff --git a/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl index 70706ca8..e9bdd97f 100644 --- a/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl +++ b/pagetop/src/base/module/demopage/locales/es-ES/demopage.ftl @@ -1,4 +1,4 @@ -module_fullname = Página de inicio predeterminada +module_name = Página de inicio predeterminada module_description = Muestra una página de demostración predeterminada cuando no hay ninguna configurada. page_title = ¡Hola mundo! diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 489b6d3b..34ac79b7 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -2,15 +2,11 @@ use crate::prelude::*; localize!("src/base/module/demopage/locales"); -pub struct DemopageModule; +pub struct Demopage; -impl ModuleTrait for DemopageModule { - fn name(&self) -> &'static str { - "Demopage" - } - - fn fullname(&self) -> String { - l("module_fullname") +impl ModuleTrait for Demopage { + fn name(&self) -> String { + l("module_name") } fn description(&self) -> Option { diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index d4f4f252..6936a019 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -2,17 +2,9 @@ use crate::prelude::*; include!(concat!(env!("OUT_DIR"), "/aliner.rs")); -pub struct AlinerTheme; - -impl ThemeTrait for AlinerTheme { - fn name(&self) -> &'static str { - "Aliner" - } - - fn fullname(&self) -> String { - "Aliner".to_owned() - } +pub struct Aliner; +impl ThemeTrait for Aliner { fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/aliner"); } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index 90111723..0445356b 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -4,17 +4,9 @@ include!(concat!(env!("OUT_DIR"), "/bootsier.rs")); localize!("src/base/theme/bootsier/locales"); -pub struct BootsierTheme; - -impl ThemeTrait for BootsierTheme { - fn name(&self) -> &'static str { - "Bootsier" - } - - fn fullname(&self) -> String { - "Bootsier".to_owned() - } +pub struct Bootsier; +impl ThemeTrait for Bootsier { fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bootsier"); } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 7454c69d..a4b194f4 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -2,17 +2,9 @@ use crate::prelude::*; include!(concat!(env!("OUT_DIR"), "/bulmix.rs")); -pub struct BulmixTheme; - -impl ThemeTrait for BulmixTheme { - fn name(&self) -> &'static str { - "Bulmix" - } - - fn fullname(&self) -> String { - "Bulmix".to_owned() - } +pub struct Bulmix; +impl ThemeTrait for Bulmix { fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bulmix"); } @@ -37,12 +29,12 @@ impl ThemeTrait for BulmixTheme { component: &mut dyn ComponentTrait, _assets: &mut PageAssets ) { - match component.name() { - "GridRow" => { + match component.type_name() { + grid::TYPENAME_ROW => { let row = component_mut::(component); row.alter_classes("columns", ClassesOp::SetDefault); }, - "GridColumn" => { + grid::TYPENAME_COLUMN => { let col = component_mut::(component); col.alter_classes("column", ClassesOp::SetDefault); }, diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs index 471b3738..d2124fb6 100644 --- a/pagetop/src/base/theme/minimal/mod.rs +++ b/pagetop/src/base/theme/minimal/mod.rs @@ -1,13 +1,6 @@ use crate::prelude::*; -pub struct MinimalTheme; +pub struct Minimal; -impl ThemeTrait for MinimalTheme { - fn name(&self) -> &'static str { - "Minimal" - } - - fn fullname(&self) -> String { - "Minimal".to_owned() - } +impl ThemeTrait for Minimal { } diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 42ad192a..fa2b6ce1 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,4 +1,4 @@ -// Exports. +// External. pub use concat_string::concat_string; pub use doc_comment::doc_comment; @@ -8,24 +8,24 @@ pub use once_cell::sync::Lazy; pub(crate) use futures::executor::block_on as run_now; -// ----------------------------------------------------------------------------- -// APIs públicas. -// ----------------------------------------------------------------------------- +// Public APIs. pub mod config; // Gestión de la configuración. pub mod trace; // Registro de trazas y eventos de la aplicación. pub mod locale; // Localización. +pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub mod db; // Acceso a la base de datos. +pub mod db; // Acceso a base de datos. -pub mod html; // Publicación de HTML desde el código. -pub mod module; // API para crear módulos con nuevas funcionalidades. -pub mod theme; // API para crear temas y temas predeterminados. +pub mod theme; // Temas predefinidos y API para crear temas. +pub mod module; // API para añadir módulos con nuevas funcionalidades. pub mod response; // Tipos de respuestas web. -pub mod app; // Aplicación y servidor web. +pub mod app; // Aplicación y servidor web. pub mod base; // Componentes, Módulos y Temas base. pub mod util; // Macros y funciones útiles. -pub mod prelude; // Re-exporta recursos comunes. +// Re-exports. + +pub mod prelude; diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 4cbd9a7d..c548f82c 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -11,11 +11,11 @@ pub use crate::{ pub use crate::config::SETTINGS; pub use crate::trace; pub use crate::localize; +pub use crate::html::*; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::{db, db::*, boxed_migration}; -pub use crate::html::*; pub use crate::theme::*; pub use crate::module::*; pub use crate::response::page::*; diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/response/page/assets.rs index 8ab4d2eb..13c28a0b 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/response/page/assets.rs @@ -6,13 +6,11 @@ use crate::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { match theme_by_name(&SETTINGS.app.theme) { Some(theme) => theme, - None => &base::theme::bootsier::BootsierTheme, + None => &base::theme::bootsier::Bootsier, } }); -// ----------------------------------------------------------------------------- // Favicon. -// ----------------------------------------------------------------------------- pub struct Favicon(Vec); @@ -99,9 +97,7 @@ impl Favicon { } } -// ----------------------------------------------------------------------------- // StyleSheet. -// ----------------------------------------------------------------------------- pub struct StyleSheet { source: &'static str, @@ -131,9 +127,7 @@ impl StyleSheet { } } -// ----------------------------------------------------------------------------- // JavaScript. -// ----------------------------------------------------------------------------- #[derive(PartialEq)] pub enum JSMode { Async, Defer, Normal } @@ -177,9 +171,7 @@ impl JavaScript { } } -// ----------------------------------------------------------------------------- // Page assets. -// ----------------------------------------------------------------------------- pub struct PageAssets { theme : &'static dyn ThemeTrait, From 21b004fc1e14562b678c65868fb88bbcb354f882 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 2 May 2022 12:43:39 +0200 Subject: [PATCH 39/80] Actualiza y concentra APIs que extienden PageTop --- pagetop/src/app/application.rs | 3 ++- pagetop/src/core/mod.rs | 3 +++ pagetop/src/{ => core}/module/all.rs | 0 pagetop/src/{ => core}/module/definition.rs | 0 pagetop/src/{ => core}/module/mod.rs | 0 pagetop/src/{ => core}/response/mod.rs | 0 pagetop/src/{ => core}/response/page/assets.rs | 2 +- pagetop/src/{ => core}/response/page/component.rs | 2 +- pagetop/src/{ => core}/response/page/container.rs | 2 +- pagetop/src/{ => core}/response/page/mod.rs | 0 pagetop/src/{ => core}/response/page/page.rs | 2 +- pagetop/src/{ => core}/theme/all.rs | 0 pagetop/src/{ => core}/theme/definition.rs | 2 +- pagetop/src/{ => core}/theme/mod.rs | 0 pagetop/src/lib.rs | 7 ++----- pagetop/src/prelude.rs | 8 +++++--- 16 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 pagetop/src/core/mod.rs rename pagetop/src/{ => core}/module/all.rs (100%) rename pagetop/src/{ => core}/module/definition.rs (100%) rename pagetop/src/{ => core}/module/mod.rs (100%) rename pagetop/src/{ => core}/response/mod.rs (100%) rename pagetop/src/{ => core}/response/page/assets.rs (99%) rename pagetop/src/{ => core}/response/page/component.rs (97%) rename pagetop/src/{ => core}/response/page/container.rs (91%) rename pagetop/src/{ => core}/response/page/mod.rs (100%) rename pagetop/src/{ => core}/response/page/page.rs (99%) rename pagetop/src/{ => core}/theme/all.rs (100%) rename pagetop/src/{ => core}/theme/definition.rs (98%) rename pagetop/src/{ => core}/theme/mod.rs (100%) diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index f183bbfc..db8af1a6 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -1,5 +1,6 @@ -use crate::{Lazy, app, base, module, theme, trace}; +use crate::{Lazy, app, base, trace}; use crate::config::SETTINGS; +use crate::core::{module, theme}; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; diff --git a/pagetop/src/core/mod.rs b/pagetop/src/core/mod.rs new file mode 100644 index 00000000..179f3e12 --- /dev/null +++ b/pagetop/src/core/mod.rs @@ -0,0 +1,3 @@ +pub mod module; // API para añadir módulos con nuevas funcionalidades. +pub mod response; // Tipos de respuestas web. +pub mod theme; // Temas predefinidos y API para crear temas. diff --git a/pagetop/src/module/all.rs b/pagetop/src/core/module/all.rs similarity index 100% rename from pagetop/src/module/all.rs rename to pagetop/src/core/module/all.rs diff --git a/pagetop/src/module/definition.rs b/pagetop/src/core/module/definition.rs similarity index 100% rename from pagetop/src/module/definition.rs rename to pagetop/src/core/module/definition.rs diff --git a/pagetop/src/module/mod.rs b/pagetop/src/core/module/mod.rs similarity index 100% rename from pagetop/src/module/mod.rs rename to pagetop/src/core/module/mod.rs diff --git a/pagetop/src/response/mod.rs b/pagetop/src/core/response/mod.rs similarity index 100% rename from pagetop/src/response/mod.rs rename to pagetop/src/core/response/mod.rs diff --git a/pagetop/src/response/page/assets.rs b/pagetop/src/core/response/page/assets.rs similarity index 99% rename from pagetop/src/response/page/assets.rs rename to pagetop/src/core/response/page/assets.rs index 13c28a0b..7eef7b1a 100644 --- a/pagetop/src/response/page/assets.rs +++ b/pagetop/src/core/response/page/assets.rs @@ -1,7 +1,7 @@ use crate::{Lazy, base, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; -use crate::theme::*; +use crate::core::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { match theme_by_name(&SETTINGS.app.theme) { diff --git a/pagetop/src/response/page/component.rs b/pagetop/src/core/response/page/component.rs similarity index 97% rename from pagetop/src/response/page/component.rs rename to pagetop/src/core/response/page/component.rs index a423707f..aa1160b1 100644 --- a/pagetop/src/response/page/component.rs +++ b/pagetop/src/core/response/page/component.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use crate::response::page::PageAssets; +use crate::core::response::page::PageAssets; use crate::util::partial_type_name; pub use std::any::Any as AnyComponent; diff --git a/pagetop/src/response/page/container.rs b/pagetop/src/core/response/page/container.rs similarity index 91% rename from pagetop/src/response/page/container.rs rename to pagetop/src/core/response/page/container.rs index 6cf09607..91c685fd 100644 --- a/pagetop/src/response/page/container.rs +++ b/pagetop/src/core/response/page/container.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use crate::response::page::{PageAssets, ComponentTrait, render_component}; +use crate::core::response::page::{PageAssets, ComponentTrait, render_component}; use std::sync::{Arc, RwLock}; diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/core/response/page/mod.rs similarity index 100% rename from pagetop/src/response/page/mod.rs rename to pagetop/src/core/response/page/mod.rs diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/core/response/page/page.rs similarity index 99% rename from pagetop/src/response/page/page.rs rename to pagetop/src/core/response/page/page.rs index 2a1f69f4..c23ea9c2 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/core/response/page/page.rs @@ -1,7 +1,7 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::response::page::*; +use crate::core::response::page::*; use std::sync::RwLock; use std::collections::HashMap; diff --git a/pagetop/src/theme/all.rs b/pagetop/src/core/theme/all.rs similarity index 100% rename from pagetop/src/theme/all.rs rename to pagetop/src/core/theme/all.rs diff --git a/pagetop/src/theme/definition.rs b/pagetop/src/core/theme/definition.rs similarity index 98% rename from pagetop/src/theme/definition.rs rename to pagetop/src/core/theme/definition.rs index ef21491a..c7d5f855 100644 --- a/pagetop/src/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -1,7 +1,7 @@ use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::response::page::{ComponentTrait, Favicon, Page, PageAssets}; +use crate::core::response::page::{ComponentTrait, Favicon, Page, PageAssets}; use crate::base::component::Chunck; use crate::util::partial_type_name; diff --git a/pagetop/src/theme/mod.rs b/pagetop/src/core/theme/mod.rs similarity index 100% rename from pagetop/src/theme/mod.rs rename to pagetop/src/core/theme/mod.rs diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index fa2b6ce1..68c23520 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -18,12 +18,9 @@ pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a base de datos. -pub mod theme; // Temas predefinidos y API para crear temas. -pub mod module; // API para añadir módulos con nuevas funcionalidades. -pub mod response; // Tipos de respuestas web. - +pub mod core; // APIs para módulos, respuestas web y temas. pub mod app; // Aplicación y servidor web. -pub mod base; // Componentes, Módulos y Temas base. +pub mod base; // Base de componentes, módulos y temas. pub mod util; // Macros y funciones útiles. // Re-exports. diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index c548f82c..d5190250 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -16,9 +16,11 @@ pub use crate::html::*; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::{db, db::*, boxed_migration}; -pub use crate::theme::*; -pub use crate::module::*; -pub use crate::response::page::*; +pub use crate::core::{ + module::*, + response::page::*, + theme::*, +}; pub use crate::app; pub use crate::app::application::{Application, essence}; From 8f429401ebc6a3f45a68b93e437fdaecfc86913f Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 2 May 2022 13:12:28 +0200 Subject: [PATCH 40/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-admin/src/summary.rs | 2 +- pagetop/Cargo.toml | 6 +++--- pagetop/src/core/theme/definition.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pagetop-admin/src/summary.rs b/pagetop-admin/src/summary.rs index 696f408d..f254714f 100644 --- a/pagetop-admin/src/summary.rs +++ b/pagetop-admin/src/summary.rs @@ -34,7 +34,7 @@ pub async fn summary() -> app::Result { Page::new() - .using_theme("bootsier") + .using_theme("Bootsier") .with_title("Admin") diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index bd2ba3a1..003bde82 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.8" +version = "0.0.9" edition = "2021" authors = [ @@ -33,9 +33,9 @@ url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } -tracing = "0.1.32" +tracing = "0.1.34" tracing-appender = "0.2.2" -tracing-subscriber = { version = "0.3.10", features = ["json", "env-filter"] } +tracing-subscriber = { version = "0.3.11", features = ["json", "env-filter"] } tracing-unwrap = { version = "0.9.2", default-features = false } tracing-actix-web = "0.2" diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index c7d5f855..1d6df035 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -92,7 +92,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { /* Cómo usarlo: - match component.name() { + match component.single_name() { "Block" => { let block = component_mut::(component); block.alter_title("New title"); @@ -112,7 +112,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { /* Cómo usarlo: - match component.name() { + match component.single_name() { "Block" => { let block = component_ref::(component); match block.template() { From 9eede3321a015fa84a8cb777334cdd0dbb077e2b Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 2 May 2022 20:00:22 +0200 Subject: [PATCH 41/80] =?UTF-8?q?A=C3=B1ade=20extensiones=20en=20m=C3=B3du?= =?UTF-8?q?los=20para=20a=C3=B1adir=20funciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/core/module/all.rs | 34 ++++++++++++++++++--- pagetop/src/core/module/definition.rs | 25 +++++++++------ pagetop/src/core/module/extension.rs | 30 ++++++++++++++++++ pagetop/src/core/module/mod.rs | 10 +++++- pagetop/src/core/response/page/component.rs | 10 +++--- pagetop/src/core/theme/definition.rs | 10 +++--- pagetop/src/util.rs | 3 +- 7 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 pagetop/src/core/module/extension.rs diff --git a/pagetop/src/core/module/all.rs b/pagetop/src/core/module/all.rs index 2e499f23..e902c1ec 100644 --- a/pagetop/src/core/module/all.rs +++ b/pagetop/src/core/module/all.rs @@ -1,14 +1,20 @@ use crate::{Lazy, app, run_now, trace}; use crate::db::*; -use super::ModuleTrait; +use super::{ExtensionTrait, ModuleTrait}; -use std::sync::RwLock; +use std::sync::{Arc, RwLock}; +use std::collections::HashMap; // Módulos registrados. static MODULES: Lazy>> = Lazy::new(|| { RwLock::new(Vec::new()) }); +// Extensiones registradas. +static EXTENSIONS: Lazy>>>> = Lazy::new(|| { + RwLock::new(HashMap::new()) +}); + pub fn register_module(module: &'static dyn ModuleTrait) { let mut list: Vec<&dyn ModuleTrait> = Vec::new(); add_to(&mut list, module); @@ -17,11 +23,24 @@ pub fn register_module(module: &'static dyn ModuleTrait) { } fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { - if !MODULES.read().unwrap().iter().any(|m| m.name() == module.name()) { - if !list.iter().any(|m| m.name() == module.name()) { + if !MODULES.read().unwrap().iter().any(|m| m.type_name() == module.type_name()) { + if !list.iter().any(|m| m.type_name() == module.type_name()) { trace::debug!("Registering \"{}\" module", module.single_name()); list.push(module); + + let mut hmap = EXTENSIONS.write().unwrap(); + for e in module.extensions().iter() { + if let Some(extensions) = hmap.get_mut(e.type_name()) { + let v = Arc::get_mut(extensions).unwrap(); + v.push(*e); + v.sort_by_key(|e| e.weight()); + } else { + hmap.insert(e.type_name(), Arc::new(vec![*e])); + } + } + + let mut dependencies = module.dependencies(); dependencies.reverse(); for d in dependencies.iter() { @@ -37,6 +56,13 @@ pub fn modules(cfg: &mut app::web::ServiceConfig) { } } +pub fn extensions(type_name: &'static str) -> Option>> { + match EXTENSIONS.read().unwrap().get(type_name) { + Some(extensions) => Some(extensions.clone()), + _ => None, + } +} + #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub fn migrations() { run_now({ diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/core/module/definition.rs index baaadd98..58a8d4ea 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/core/module/definition.rs @@ -1,15 +1,16 @@ -use crate::app; -use crate::util::partial_type_name; +use crate::{app, util}; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; +use super::ExtensionTrait; + pub trait BaseModule { fn type_name(&self) -> &'static str; fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: usize) -> &'static str; + fn qualified_name(&self, last: u8) -> &'static str; } /// Los módulos deben implementar este *trait*. @@ -22,19 +23,23 @@ pub trait ModuleTrait: BaseModule + Send + Sync { None } - fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { - vec![] - } - #[allow(unused_variables)] fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { } + fn extensions(&self) -> Vec<&'static dyn ExtensionTrait> { + vec![] + } + #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[allow(unused_variables)] fn migrations(&self) -> Vec> { vec![] } + + fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } } impl BaseModule for M { @@ -43,10 +48,10 @@ impl BaseModule for M { } fn single_name(&self) -> &'static str { - partial_type_name(std::any::type_name::(), 1) + util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: usize) -> &'static str { - partial_type_name(std::any::type_name::(), last) + fn qualified_name(&self, last: u8) -> &'static str { + util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/core/module/extension.rs b/pagetop/src/core/module/extension.rs new file mode 100644 index 00000000..e8b8107c --- /dev/null +++ b/pagetop/src/core/module/extension.rs @@ -0,0 +1,30 @@ +use crate::util; + +pub trait BaseExtension { + fn type_name(&self) -> &'static str; + + fn single_name(&self) -> &'static str; + + fn qualified_name(&self, last: u8) -> &'static str; +} + +/// Las extensiones deben extender este *trait*. +pub trait ExtensionTrait: BaseExtension + Send + Sync { + fn weight(&self) -> i8 { + 0 + } +} + +impl BaseExtension for E { + fn type_name(&self) -> &'static str { + std::any::type_name::() + } + + fn single_name(&self) -> &'static str { + util::partial_type_name(std::any::type_name::(), 1) + } + + fn qualified_name(&self, last: u8) -> &'static str { + util::partial_type_name(std::any::type_name::(), last) + } +} diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module/mod.rs index 720d806c..d72bd48d 100644 --- a/pagetop/src/core/module/mod.rs +++ b/pagetop/src/core/module/mod.rs @@ -3,6 +3,14 @@ pub use definition::{ BaseModule, ModuleTrait, }; +mod extension; +pub use extension::{ + BaseExtension, + ExtensionTrait, +}; pub(crate) mod all; -pub use all::register_module; \ No newline at end of file +pub use all::{ + extensions, + register_module +}; diff --git a/pagetop/src/core/response/page/component.rs b/pagetop/src/core/response/page/component.rs index aa1160b1..0bbc3abf 100644 --- a/pagetop/src/core/response/page/component.rs +++ b/pagetop/src/core/response/page/component.rs @@ -1,6 +1,6 @@ use crate::html::{Markup, html}; use crate::core::response::page::PageAssets; -use crate::util::partial_type_name; +use crate::util; pub use std::any::Any as AnyComponent; @@ -9,7 +9,7 @@ pub trait BaseComponent { fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: usize) -> &'static str; + fn qualified_name(&self, last: u8) -> &'static str; } pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { @@ -52,11 +52,11 @@ impl BaseComponent for C { } fn single_name(&self) -> &'static str { - partial_type_name(std::any::type_name::(), 1) + util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: usize) -> &'static str { - partial_type_name(std::any::type_name::(), last) + fn qualified_name(&self, last: u8) -> &'static str { + util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 1d6df035..130dfdac 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -3,14 +3,14 @@ use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::core::response::page::{ComponentTrait, Favicon, Page, PageAssets}; use crate::base::component::Chunck; -use crate::util::partial_type_name; +use crate::util; pub trait BaseTheme { fn type_name(&self) -> &'static str; fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: usize) -> &'static str; + fn qualified_name(&self, last: u8) -> &'static str; } /// Los temas deben implementar este "trait". @@ -143,10 +143,10 @@ impl BaseTheme for T { } fn single_name(&self) -> &'static str { - partial_type_name(std::any::type_name::(), 1) + util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: usize) -> &'static str { - partial_type_name(std::any::type_name::(), last) + fn qualified_name(&self, last: u8) -> &'static str { + util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index ca4a96fc..3190b641 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -47,11 +47,12 @@ macro_rules! theme_static_files { }}; } -pub(crate) fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { +pub(crate) fn partial_type_name(type_name: &'static str, last: u8) -> &'static str { if last == 0 { return type_name; } let positions: Vec<_> = type_name.rmatch_indices("::").collect(); + let last: usize = last as usize; if positions.len() < last { return type_name; } From d0e566aede64683e2d8ccfbe9bd014120aebd278 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 4 May 2022 18:07:56 +0200 Subject: [PATCH 42/80] Modifica las extensiones por acciones registradas --- pagetop/src/api/action/all.rs | 27 ++++++++ .../extension.rs => api/action/definition.rs} | 17 +++-- pagetop/src/api/action/holder.rs | 30 +++++++++ pagetop/src/api/action/mod.rs | 19 ++++++ pagetop/src/api/component/action.rs | 55 ++++++++++++++++ pagetop/src/api/component/all.rs | 22 +++++++ .../response/page => api/component}/assets.rs | 2 +- .../page => api/component}/container.rs | 2 +- .../component/definition.rs} | 28 ++++++++- .../response/page => api/component}/mod.rs | 16 +++-- pagetop/src/api/mod.rs | 4 ++ pagetop/src/{core => api}/module/all.rs | 30 +-------- .../src/{core => api}/module/definition.rs | 6 -- pagetop/src/api/module/mod.rs | 10 +++ pagetop/src/{core => api}/theme/all.rs | 0 pagetop/src/{core => api}/theme/definition.rs | 3 +- pagetop/src/{core => api}/theme/mod.rs | 0 pagetop/src/app/application.rs | 2 +- pagetop/src/core/mod.rs | 3 - pagetop/src/core/module/mod.rs | 16 ----- pagetop/src/lib.rs | 4 +- pagetop/src/prelude.rs | 7 ++- pagetop/src/{core => }/response/mod.rs | 0 pagetop/src/response/page/action.rs | 63 +++++++++++++++++++ pagetop/src/response/page/mod.rs | 4 ++ pagetop/src/{core => }/response/page/page.rs | 39 +++--------- 26 files changed, 309 insertions(+), 100 deletions(-) create mode 100644 pagetop/src/api/action/all.rs rename pagetop/src/{core/module/extension.rs => api/action/definition.rs} (59%) create mode 100644 pagetop/src/api/action/holder.rs create mode 100644 pagetop/src/api/action/mod.rs create mode 100644 pagetop/src/api/component/action.rs create mode 100644 pagetop/src/api/component/all.rs rename pagetop/src/{core/response/page => api/component}/assets.rs (99%) rename pagetop/src/{core/response/page => api/component}/container.rs (91%) rename pagetop/src/{core/response/page/component.rs => api/component/definition.rs} (64%) rename pagetop/src/{core/response/page => api/component}/mod.rs (67%) create mode 100644 pagetop/src/api/mod.rs rename pagetop/src/{core => api}/module/all.rs (63%) rename pagetop/src/{core => api}/module/definition.rs (91%) create mode 100644 pagetop/src/api/module/mod.rs rename pagetop/src/{core => api}/theme/all.rs (100%) rename pagetop/src/{core => api}/theme/definition.rs (97%) rename pagetop/src/{core => api}/theme/mod.rs (100%) delete mode 100644 pagetop/src/core/mod.rs delete mode 100644 pagetop/src/core/module/mod.rs rename pagetop/src/{core => }/response/mod.rs (100%) create mode 100644 pagetop/src/response/page/action.rs create mode 100644 pagetop/src/response/page/mod.rs rename pagetop/src/{core => }/response/page/page.rs (82%) diff --git a/pagetop/src/api/action/all.rs b/pagetop/src/api/action/all.rs new file mode 100644 index 00000000..e7a4981f --- /dev/null +++ b/pagetop/src/api/action/all.rs @@ -0,0 +1,27 @@ +use crate::Lazy; +use super::{ActionItem, ActionsHolder, ActionTrait}; + +use std::sync::RwLock; +use std::collections::HashMap; + +// Registered actions. +static ACTIONS: Lazy>> = Lazy::new(|| { + RwLock::new(HashMap::new()) +}); + +pub fn register_action(action: impl ActionTrait) { + let mut hmap = ACTIONS.write().unwrap(); + let action_name = action.type_name(); + if let Some(actions) = hmap.get_mut(action_name) { + actions.add(action); + } else { + hmap.insert(action_name, ActionsHolder::new_with(action)); + } +} + +pub fn run_actions(type_name: &'static str, f: F) where F: FnMut(&ActionItem) -> B { + let hmap = ACTIONS.read().unwrap(); + if let Some(actions) = hmap.get(type_name) { + actions.iter_map(f) + } +} diff --git a/pagetop/src/core/module/extension.rs b/pagetop/src/api/action/definition.rs similarity index 59% rename from pagetop/src/core/module/extension.rs rename to pagetop/src/api/action/definition.rs index e8b8107c..4a813ef9 100644 --- a/pagetop/src/core/module/extension.rs +++ b/pagetop/src/api/action/definition.rs @@ -1,6 +1,8 @@ use crate::util; -pub trait BaseExtension { +pub use std::any::Any as AnyAction; + +pub trait BaseAction { fn type_name(&self) -> &'static str; fn single_name(&self) -> &'static str; @@ -8,14 +10,17 @@ pub trait BaseExtension { fn qualified_name(&self, last: u8) -> &'static str; } -/// Las extensiones deben extender este *trait*. -pub trait ExtensionTrait: BaseExtension + Send + Sync { +pub trait ActionTrait: AnyAction + BaseAction + Send + Sync { + fn new() -> Self where Self: Sized; + fn weight(&self) -> i8 { 0 } + + fn as_ref_any(&self) -> &dyn AnyAction; } -impl BaseExtension for E { +impl BaseAction for C { fn type_name(&self) -> &'static str { std::any::type_name::() } @@ -28,3 +33,7 @@ impl BaseExtension for E { util::partial_type_name(std::any::type_name::(), last) } } + +pub fn action_ref(action: &dyn ActionTrait) -> &A { + action.as_ref_any().downcast_ref::().unwrap() +} diff --git a/pagetop/src/api/action/holder.rs b/pagetop/src/api/action/holder.rs new file mode 100644 index 00000000..c7dd3ef3 --- /dev/null +++ b/pagetop/src/api/action/holder.rs @@ -0,0 +1,30 @@ +use super::ActionTrait; + +use std::sync::{Arc, RwLock}; + +pub type ActionItem = Box; + +#[derive(Clone)] +pub struct ActionsHolder(Arc>>); + +impl ActionsHolder { + pub fn new() -> Self { + ActionsHolder(Arc::new(RwLock::new(Vec::new()))) + } + + pub fn new_with(action: impl ActionTrait) -> Self { + let mut container = ActionsHolder::new(); + container.add(action); + container + } + + pub fn add(&mut self, action: impl ActionTrait) { + let mut actions = self.0.write().unwrap(); + actions.push(Box::new(action)); + actions.sort_by_key(|a| a.weight()); + } + + pub fn iter_map(&self, f: F) where Self: Sized, F: FnMut(&ActionItem) -> B { + let _ = self.0.read().unwrap().iter().map(f); + } +} diff --git a/pagetop/src/api/action/mod.rs b/pagetop/src/api/action/mod.rs new file mode 100644 index 00000000..e28122e0 --- /dev/null +++ b/pagetop/src/api/action/mod.rs @@ -0,0 +1,19 @@ +mod definition; +pub use definition::{ + ActionTrait, + AnyAction, + BaseAction, + action_ref, +}; + +mod holder; +pub use holder::{ + ActionItem, + ActionsHolder, +}; + +mod all; +pub use all::{ + register_action, + run_actions, +}; diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs new file mode 100644 index 00000000..2569be85 --- /dev/null +++ b/pagetop/src/api/component/action.rs @@ -0,0 +1,55 @@ +use crate::api::action::{ActionTrait, AnyAction}; +use super::{ComponentTrait, PageAssets}; + +pub enum TypeAction { + BeforeRenderComponent(fn(&mut dyn ComponentTrait, &mut PageAssets)), + None, +} + +pub struct ComponentAction { + action: TypeAction, + weight: i8, +} + +impl ActionTrait for ComponentAction { + fn new() -> Self { + ComponentAction { + action: TypeAction::None, + weight: 0, + } + } + + fn weight(&self) -> i8 { + self.weight + } + + fn as_ref_any(&self) -> &dyn AnyAction { + self + } +} + +impl ComponentAction { + pub fn new(action: TypeAction) -> Self { + ComponentAction { + action, + weight: 0, + } + } + + pub fn new_with_weight(action: TypeAction, weight: i8) -> Self { + ComponentAction { + action, + weight, + } + } + + pub fn before_render_component( + &self, + component: &mut dyn ComponentTrait, + assets: &mut PageAssets) + { + if let TypeAction::BeforeRenderComponent(f) = self.action { + f(component, assets) + } + } +} diff --git a/pagetop/src/api/component/all.rs b/pagetop/src/api/component/all.rs new file mode 100644 index 00000000..6ba66752 --- /dev/null +++ b/pagetop/src/api/component/all.rs @@ -0,0 +1,22 @@ +use crate::Lazy; +use super::{ComponentTrait, PageContainer}; + +use std::sync::RwLock; +use std::collections::HashMap; + +static COMPONENTS: Lazy>> = Lazy::new(|| { + RwLock::new(HashMap::new()) +}); + +pub fn add_component_to(region: &'static str, component: impl ComponentTrait) { + let mut hmap = COMPONENTS.write().unwrap(); + if let Some(regions) = hmap.get_mut(region) { + regions.add(component); + } else { + hmap.insert(region, PageContainer::new_with(component)); + } +} + +pub fn common_components() -> HashMap<&'static str, PageContainer> { + COMPONENTS.read().unwrap().clone() +} diff --git a/pagetop/src/core/response/page/assets.rs b/pagetop/src/api/component/assets.rs similarity index 99% rename from pagetop/src/core/response/page/assets.rs rename to pagetop/src/api/component/assets.rs index 7eef7b1a..16821ada 100644 --- a/pagetop/src/core/response/page/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -1,7 +1,7 @@ use crate::{Lazy, base, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; -use crate::core::theme::*; +use crate::api::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { match theme_by_name(&SETTINGS.app.theme) { diff --git a/pagetop/src/core/response/page/container.rs b/pagetop/src/api/component/container.rs similarity index 91% rename from pagetop/src/core/response/page/container.rs rename to pagetop/src/api/component/container.rs index 91c685fd..5ca41056 100644 --- a/pagetop/src/core/response/page/container.rs +++ b/pagetop/src/api/component/container.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use crate::core::response::page::{PageAssets, ComponentTrait, render_component}; +use super::{PageAssets, ComponentTrait, render_component}; use std::sync::{Arc, RwLock}; diff --git a/pagetop/src/core/response/page/component.rs b/pagetop/src/api/component/definition.rs similarity index 64% rename from pagetop/src/core/response/page/component.rs rename to pagetop/src/api/component/definition.rs index 0bbc3abf..d32f1b3f 100644 --- a/pagetop/src/core/response/page/component.rs +++ b/pagetop/src/api/component/definition.rs @@ -1,6 +1,8 @@ use crate::html::{Markup, html}; -use crate::core::response::page::PageAssets; use crate::util; +use crate::api::action::{action_ref, run_actions}; +use super::PageAssets; +use super::action::ComponentAction; pub use std::any::Any as AnyComponent; @@ -67,3 +69,27 @@ pub fn component_ref(component: &dyn ComponentTrait) -> &C { pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { component.as_mut_any().downcast_mut::().unwrap() } + +pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut PageAssets) -> Markup { + // Acciones del componente antes de renderizar. + component.before_render(assets); + + // Acciones de los módulos antes de renderizar el componente. + run_actions( + "", + |a| action_ref::(&**a).before_render_component(component, assets) + ); + + // Acciones del tema antes de renderizar el componente. + assets.theme().before_render_component(component, assets); + + match component.is_renderable() { + true => { + match assets.theme().render_component(component, assets) { + Some(html) => html, + None => component.default_render(assets) + } + }, + false => html! {} + } +} diff --git a/pagetop/src/core/response/page/mod.rs b/pagetop/src/api/component/mod.rs similarity index 67% rename from pagetop/src/core/response/page/mod.rs rename to pagetop/src/api/component/mod.rs index 01add24f..7c9482c6 100644 --- a/pagetop/src/core/response/page/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -1,3 +1,5 @@ +pub mod action; + mod assets; pub use assets::{ Favicon, @@ -6,22 +8,24 @@ pub use assets::{ PageAssets, }; -mod component; -pub use component::{ +mod definition; +pub use definition::{ AnyComponent, BaseComponent, ComponentTrait, component_ref, component_mut, }; +use definition::render_component; mod container; pub use container::PageContainer; -mod page; -pub use page::Page; -pub use page::render_component; -pub use page::add_component_to; +mod all; +pub use all::{ + add_component_to, + common_components, +}; pub fn render_always() -> bool { true } diff --git a/pagetop/src/api/mod.rs b/pagetop/src/api/mod.rs new file mode 100644 index 00000000..b69ec91b --- /dev/null +++ b/pagetop/src/api/mod.rs @@ -0,0 +1,4 @@ +pub mod action; // API to define functions that alter the behavior of PageTop core. +pub mod component; // API para crear nuevos componentes. +pub mod module; // API para añadir módulos con nuevas funcionalidades. +pub mod theme; // API para crear temas. diff --git a/pagetop/src/core/module/all.rs b/pagetop/src/api/module/all.rs similarity index 63% rename from pagetop/src/core/module/all.rs rename to pagetop/src/api/module/all.rs index e902c1ec..56e1d6c4 100644 --- a/pagetop/src/core/module/all.rs +++ b/pagetop/src/api/module/all.rs @@ -1,20 +1,14 @@ use crate::{Lazy, app, run_now, trace}; use crate::db::*; -use super::{ExtensionTrait, ModuleTrait}; +use super::ModuleTrait; -use std::sync::{Arc, RwLock}; -use std::collections::HashMap; +use std::sync::RwLock; // Módulos registrados. static MODULES: Lazy>> = Lazy::new(|| { RwLock::new(Vec::new()) }); -// Extensiones registradas. -static EXTENSIONS: Lazy>>>> = Lazy::new(|| { - RwLock::new(HashMap::new()) -}); - pub fn register_module(module: &'static dyn ModuleTrait) { let mut list: Vec<&dyn ModuleTrait> = Vec::new(); add_to(&mut list, module); @@ -28,19 +22,6 @@ fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { trace::debug!("Registering \"{}\" module", module.single_name()); list.push(module); - - let mut hmap = EXTENSIONS.write().unwrap(); - for e in module.extensions().iter() { - if let Some(extensions) = hmap.get_mut(e.type_name()) { - let v = Arc::get_mut(extensions).unwrap(); - v.push(*e); - v.sort_by_key(|e| e.weight()); - } else { - hmap.insert(e.type_name(), Arc::new(vec![*e])); - } - } - - let mut dependencies = module.dependencies(); dependencies.reverse(); for d in dependencies.iter() { @@ -56,13 +37,6 @@ pub fn modules(cfg: &mut app::web::ServiceConfig) { } } -pub fn extensions(type_name: &'static str) -> Option>> { - match EXTENSIONS.read().unwrap().get(type_name) { - Some(extensions) => Some(extensions.clone()), - _ => None, - } -} - #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub fn migrations() { run_now({ diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/api/module/definition.rs similarity index 91% rename from pagetop/src/core/module/definition.rs rename to pagetop/src/api/module/definition.rs index 58a8d4ea..288e99bb 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -3,8 +3,6 @@ use crate::{app, util}; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db; -use super::ExtensionTrait; - pub trait BaseModule { fn type_name(&self) -> &'static str; @@ -27,10 +25,6 @@ pub trait ModuleTrait: BaseModule + Send + Sync { fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { } - fn extensions(&self) -> Vec<&'static dyn ExtensionTrait> { - vec![] - } - #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[allow(unused_variables)] fn migrations(&self) -> Vec> { diff --git a/pagetop/src/api/module/mod.rs b/pagetop/src/api/module/mod.rs new file mode 100644 index 00000000..d1addefe --- /dev/null +++ b/pagetop/src/api/module/mod.rs @@ -0,0 +1,10 @@ +mod definition; +pub use definition::{ + BaseModule, + ModuleTrait, +}; + +pub(crate) mod all; +pub use all::{ + register_module, +}; diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/api/theme/all.rs similarity index 100% rename from pagetop/src/core/theme/all.rs rename to pagetop/src/api/theme/all.rs diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/api/theme/definition.rs similarity index 97% rename from pagetop/src/core/theme/definition.rs rename to pagetop/src/api/theme/definition.rs index 130dfdac..11551680 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -1,7 +1,8 @@ use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::core::response::page::{ComponentTrait, Favicon, Page, PageAssets}; +use crate::api::component::{ComponentTrait, Favicon, PageAssets}; +use crate::response::page::Page; use crate::base::component::Chunck; use crate::util; diff --git a/pagetop/src/core/theme/mod.rs b/pagetop/src/api/theme/mod.rs similarity index 100% rename from pagetop/src/core/theme/mod.rs rename to pagetop/src/api/theme/mod.rs diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index db8af1a6..1b7564ea 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -1,6 +1,6 @@ use crate::{Lazy, app, base, trace}; use crate::config::SETTINGS; -use crate::core::{module, theme}; +use crate::api::{module, theme}; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; diff --git a/pagetop/src/core/mod.rs b/pagetop/src/core/mod.rs deleted file mode 100644 index 179f3e12..00000000 --- a/pagetop/src/core/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod module; // API para añadir módulos con nuevas funcionalidades. -pub mod response; // Tipos de respuestas web. -pub mod theme; // Temas predefinidos y API para crear temas. diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module/mod.rs deleted file mode 100644 index d72bd48d..00000000 --- a/pagetop/src/core/module/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -mod definition; -pub use definition::{ - BaseModule, - ModuleTrait, -}; -mod extension; -pub use extension::{ - BaseExtension, - ExtensionTrait, -}; - -pub(crate) mod all; -pub use all::{ - extensions, - register_module -}; diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 68c23520..fd843285 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -18,7 +18,9 @@ pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a base de datos. -pub mod core; // APIs para módulos, respuestas web y temas. +pub mod api; // Main APIs for actions, components, modules and themes. + +pub mod response; // Tipos de respuestas web. pub mod app; // Aplicación y servidor web. pub mod base; // Base de componentes, módulos y temas. pub mod util; // Macros y funciones útiles. diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index d5190250..079deb63 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -16,12 +16,15 @@ pub use crate::html::*; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub use crate::{db, db::*, boxed_migration}; -pub use crate::core::{ +pub use crate::api::{ + action::*, + component::*, module::*, - response::page::*, theme::*, }; +pub use crate::response::page::*; + pub use crate::app; pub use crate::app::application::{Application, essence}; diff --git a/pagetop/src/core/response/mod.rs b/pagetop/src/response/mod.rs similarity index 100% rename from pagetop/src/core/response/mod.rs rename to pagetop/src/response/mod.rs diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs new file mode 100644 index 00000000..e3173d7f --- /dev/null +++ b/pagetop/src/response/page/action.rs @@ -0,0 +1,63 @@ +use crate::api::action::{ActionTrait, AnyAction}; +use crate::api::component::{ComponentTrait, PageAssets}; +use super::Page; + +pub enum TypeAction { + BeforeRenderPage(fn(&mut Page)), + BeforeRenderComponent(fn(&mut dyn ComponentTrait, &mut PageAssets)), + None, +} + +pub struct PageAction { + action: TypeAction, + weight: i8, +} + +impl ActionTrait for PageAction { + fn new() -> Self { + PageAction { + action: TypeAction::None, + weight: 0, + } + } + + fn weight(&self) -> i8 { + self.weight + } + + fn as_ref_any(&self) -> &dyn AnyAction { + self + } +} + +impl PageAction { + pub fn new(action: TypeAction) -> Self { + PageAction { + action, + weight: 0, + } + } + + pub fn new_with_weight(action: TypeAction, weight: i8) -> Self { + PageAction { + action, + weight, + } + } + + pub fn before_render_page(&self, page: &mut Page) { + if let TypeAction::BeforeRenderPage(f) = self.action { + f(page) + } + } + + pub fn before_render_component( + &self, + component: &mut dyn ComponentTrait, + assets: &mut PageAssets) + { + if let TypeAction::BeforeRenderComponent(f) = self.action { + f(component, assets) + } + } +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs new file mode 100644 index 00000000..097bde8b --- /dev/null +++ b/pagetop/src/response/page/mod.rs @@ -0,0 +1,4 @@ +pub mod action; + +mod page; +pub use page::Page; diff --git a/pagetop/src/core/response/page/page.rs b/pagetop/src/response/page/page.rs similarity index 82% rename from pagetop/src/core/response/page/page.rs rename to pagetop/src/response/page/page.rs index c23ea9c2..b52566a8 100644 --- a/pagetop/src/core/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,14 +1,12 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::core::response::page::*; +use crate::api::action::{action_ref, run_actions}; +use crate::api::component::*; -use std::sync::RwLock; use std::collections::HashMap; -static COMPONENTS: Lazy>> = Lazy::new(|| { - RwLock::new(HashMap::new()) -}); +use super::action::PageAction; static DEFAULT_LANGUAGE: Lazy> = Lazy::new(|| { let language = SETTINGS.app.language[..2].to_lowercase(); @@ -65,7 +63,7 @@ impl<'a> Page<'a> { title : OptAttr::new(), description : OptAttr::new(), assets : PageAssets::new(), - regions : COMPONENTS.read().unwrap().clone(), + regions : common_components(), body_classes: Classes::new_with_default("body"), template : "default".to_owned(), } @@ -153,6 +151,12 @@ impl<'a> Page<'a> { // Page RENDER. pub fn render(&mut self) -> app::Result { + // Acciones de los módulos antes de renderizar el tema. + run_actions( + "", + |a| action_ref::(&**a).before_render_page(self) + ); + // Acciones del tema antes de renderizar la página. self.assets.theme().before_render_page(self); @@ -186,26 +190,3 @@ impl<'a> Page<'a> { self } } - -pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut PageAssets) -> Markup { - component.before_render(assets); - assets.theme().before_render_component(component, assets); - match component.is_renderable() { - true => { - match assets.theme().render_component(component, assets) { - Some(html) => html, - None => component.default_render(assets) - } - }, - false => html! {} - } -} - -pub fn add_component_to(region: &'static str, component: impl ComponentTrait) { - let mut hmap = COMPONENTS.write().unwrap(); - if let Some(regions) = hmap.get_mut(region) { - regions.add(component); - } else { - hmap.insert(region, PageContainer::new_with(component)); - } -} From 7c8f51ba86b41f65849fddbb4f4c7bab12b642e2 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 4 May 2022 18:21:36 +0200 Subject: [PATCH 43/80] =?UTF-8?q?Modifica=20tipos=20num=C3=A9ricos=20por?= =?UTF-8?q?=20isize/usize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/api/action/definition.rs | 6 +++--- pagetop/src/api/component/action.rs | 6 +++--- pagetop/src/api/component/assets.rs | 16 ++++++++-------- pagetop/src/api/component/definition.rs | 6 +++--- pagetop/src/api/module/definition.rs | 4 ++-- pagetop/src/api/theme/definition.rs | 4 ++-- pagetop/src/base/component/block.rs | 8 ++++---- pagetop/src/base/component/chunck.rs | 8 ++++---- pagetop/src/base/component/container.rs | 8 ++++---- pagetop/src/base/component/form/button.rs | 8 ++++---- pagetop/src/base/component/form/date.rs | 8 ++++---- pagetop/src/base/component/form/form.rs | 8 ++++---- pagetop/src/base/component/form/hidden.rs | 8 ++++---- pagetop/src/base/component/form/input.rs | 8 ++++---- pagetop/src/base/component/grid/column.rs | 8 ++++---- pagetop/src/base/component/grid/row.rs | 8 ++++---- pagetop/src/base/component/image.rs | 8 ++++---- pagetop/src/base/component/menu.rs | 16 ++++++++-------- pagetop/src/response/page/action.rs | 6 +++--- pagetop/src/util.rs | 3 +-- 20 files changed, 77 insertions(+), 78 deletions(-) diff --git a/pagetop/src/api/action/definition.rs b/pagetop/src/api/action/definition.rs index 4a813ef9..e0bab945 100644 --- a/pagetop/src/api/action/definition.rs +++ b/pagetop/src/api/action/definition.rs @@ -7,13 +7,13 @@ pub trait BaseAction { fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: u8) -> &'static str; + fn qualified_name(&self, last: usize) -> &'static str; } pub trait ActionTrait: AnyAction + BaseAction + Send + Sync { fn new() -> Self where Self: Sized; - fn weight(&self) -> i8 { + fn weight(&self) -> isize { 0 } @@ -29,7 +29,7 @@ impl BaseAction for C { util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: u8) -> &'static str { + fn qualified_name(&self, last: usize) -> &'static str { util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs index 2569be85..6479cc11 100644 --- a/pagetop/src/api/component/action.rs +++ b/pagetop/src/api/component/action.rs @@ -8,7 +8,7 @@ pub enum TypeAction { pub struct ComponentAction { action: TypeAction, - weight: i8, + weight: isize, } impl ActionTrait for ComponentAction { @@ -19,7 +19,7 @@ impl ActionTrait for ComponentAction { } } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -36,7 +36,7 @@ impl ComponentAction { } } - pub fn new_with_weight(action: TypeAction, weight: i8) -> Self { + pub fn new_with_weight(action: TypeAction, weight: isize) -> Self { ComponentAction { action, weight, diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/api/component/assets.rs index 16821ada..c7faf1bc 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -101,7 +101,7 @@ impl Favicon { pub struct StyleSheet { source: &'static str, - weight: i8, + weight: isize, } impl StyleSheet { pub fn source(s: &'static str) -> Self { @@ -111,12 +111,12 @@ impl StyleSheet { } } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.weight = weight; self } - pub fn weight(self) -> i8 { + pub fn weight(self) -> isize { self.weight } @@ -134,7 +134,7 @@ pub enum JSMode { Async, Defer, Normal } pub struct JavaScript { source: &'static str, - weight: i8, + weight: isize, mode : JSMode, } impl JavaScript { @@ -146,7 +146,7 @@ impl JavaScript { } } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.weight = weight; self } @@ -156,7 +156,7 @@ impl JavaScript { self } - pub fn weight(self) -> i8 { + pub fn weight(self) -> isize { self.weight } @@ -180,7 +180,7 @@ pub struct PageAssets { stylesheets: Vec, javascripts: Vec, with_jquery: bool, - id_counter : u32, + id_counter : usize, } impl PageAssets { @@ -239,7 +239,7 @@ impl PageAssets { JavaScript::source( "/theme/js/jquery.min.js?ver=3.6.0" ) - .with_weight(i8::MIN) + .with_weight(isize::MIN) .with_mode(JSMode::Normal) ); self.with_jquery = true; diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index d32f1b3f..f7c1df43 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -11,7 +11,7 @@ pub trait BaseComponent { fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: u8) -> &'static str; + fn qualified_name(&self, last: usize) -> &'static str; } pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { @@ -30,7 +30,7 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { true } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { 0 } @@ -57,7 +57,7 @@ impl BaseComponent for C { util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: u8) -> &'static str { + fn qualified_name(&self, last: usize) -> &'static str { util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index 288e99bb..837304f3 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -8,7 +8,7 @@ pub trait BaseModule { fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: u8) -> &'static str; + fn qualified_name(&self, last: usize) -> &'static str; } /// Los módulos deben implementar este *trait*. @@ -45,7 +45,7 @@ impl BaseModule for M { util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: u8) -> &'static str { + fn qualified_name(&self, last: usize) -> &'static str { util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/api/theme/definition.rs index 11551680..08d913e6 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -11,7 +11,7 @@ pub trait BaseTheme { fn single_name(&self) -> &'static str; - fn qualified_name(&self, last: u8) -> &'static str; + fn qualified_name(&self, last: usize) -> &'static str; } /// Los temas deben implementar este "trait". @@ -147,7 +147,7 @@ impl BaseTheme for T { util::partial_type_name(std::any::type_name::(), 1) } - fn qualified_name(&self, last: u8) -> &'static str { + fn qualified_name(&self, last: usize) -> &'static str { util::partial_type_name(std::any::type_name::(), last) } } diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 96dc06b6..b1407d60 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -4,7 +4,7 @@ pub const TYPENAME_BLOCK: &str = "pagetop::base::component::block::Block"; pub struct Block { renderable: fn() -> bool, - weight : i8, + weight : isize, components: PageContainer, title : OptAttr, id : OptIden, @@ -29,7 +29,7 @@ impl ComponentTrait for Block { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -77,7 +77,7 @@ impl Block { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -109,7 +109,7 @@ impl Block { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 902b1eef..26666344 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -4,7 +4,7 @@ pub const TYPENAME_CHUNCK: &str = "pagetop::base::component::chunck::Chunck"; pub struct Chunck { renderable: fn() -> bool, - weight : i8, + weight : isize, html : Markup, template : String, } @@ -23,7 +23,7 @@ impl ComponentTrait for Chunck { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -52,7 +52,7 @@ impl Chunck { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -74,7 +74,7 @@ impl Chunck { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 2bfbc3e0..dbc58ce6 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -6,7 +6,7 @@ pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable : fn() -> bool, - weight : i8, + weight : isize, components : PageContainer, container : ContainerType, id : OptIden, @@ -33,7 +33,7 @@ impl ComponentTrait for Container { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -127,7 +127,7 @@ impl Container { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -159,7 +159,7 @@ impl Container { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 783adbc6..16720106 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -6,7 +6,7 @@ pub enum ButtonType {Button, Reset, Submit} pub struct Button { renderable : fn() -> bool, - weight : i8, + weight : isize, button_type: ButtonType, name : OptAttr, value : OptAttr, @@ -36,7 +36,7 @@ impl ComponentTrait for Button { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -105,7 +105,7 @@ impl Button { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -147,7 +147,7 @@ impl Button { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 7ef3f82d..741ac450 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -4,7 +4,7 @@ pub const TYPENAME_DATE: &str = "pagetop::base::component::form::date::Date"; pub struct Date { renderable : fn() -> bool, - weight : i8, + weight : isize, name : OptAttr, value : OptAttr, label : OptAttr, @@ -44,7 +44,7 @@ impl ComponentTrait for Date { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -105,7 +105,7 @@ impl Date { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -177,7 +177,7 @@ impl Date { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index e6b10261..0ddb99eb 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -6,7 +6,7 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, - weight : i8, + weight : isize, elements : PageContainer, action : OptAttr, charset : OptAttr, @@ -35,7 +35,7 @@ impl ComponentTrait for Form { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -86,7 +86,7 @@ impl Form { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -128,7 +128,7 @@ impl Form { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 3e9b41f3..4df5fd4f 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -3,7 +3,7 @@ use crate::prelude::*; pub const TYPENAME_HIDDEN: &str = "pagetop::base::component::form::hidden::Hidden"; pub struct Hidden { - weight: i8, + weight: isize, name : OptIden, value : OptAttr, } @@ -17,7 +17,7 @@ impl ComponentTrait for Hidden { } } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -47,7 +47,7 @@ impl Hidden { // Hidden BUILDER. - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -64,7 +64,7 @@ impl Hidden { // Hidden ALTER. - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 7a45ce21..573ddebf 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -6,7 +6,7 @@ pub enum InputType {Email, Password, Search, Telephone, Textfield, Url} pub struct Input { renderable : fn() -> bool, - weight : i8, + weight : isize, input_type : InputType, name : OptIden, value : OptAttr, @@ -54,7 +54,7 @@ impl ComponentTrait for Input { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -171,7 +171,7 @@ impl Input { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -258,7 +258,7 @@ impl Input { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index b4121549..add535e3 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -4,7 +4,7 @@ pub const TYPENAME_COLUMN: &str = "pagetop::base::component::grid::column::Colum pub struct Column { renderable: fn() -> bool, - weight : i8, + weight : isize, components: PageContainer, id : OptIden, classes : Classes, @@ -27,7 +27,7 @@ impl ComponentTrait for Column { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -68,7 +68,7 @@ impl Column { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -95,7 +95,7 @@ impl Column { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 8077fec6..d8a8858a 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -4,7 +4,7 @@ pub const TYPENAME_ROW: &str = "pagetop::base::component::grid::row::Row"; pub struct Row { renderable: fn() -> bool, - weight : i8, + weight : isize, columns : PageContainer, id : OptIden, classes : Classes, @@ -27,7 +27,7 @@ impl ComponentTrait for Row { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -68,7 +68,7 @@ impl Row { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -95,7 +95,7 @@ impl Row { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index b88ead07..ee92215a 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -4,7 +4,7 @@ pub const TYPENAME_IMAGE: &str = "pagetop::base::component::image::Image"; pub struct Image { renderable: fn() -> bool, - weight : i8, + weight : isize, source : OptAttr, id : OptIden, classes : Classes, @@ -27,7 +27,7 @@ impl ComponentTrait for Image { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -61,7 +61,7 @@ impl Image { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -93,7 +93,7 @@ impl Image { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 845284f9..f0bd2a40 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -17,7 +17,7 @@ pub enum MenuItemType { pub struct MenuItem { renderable: fn() -> bool, - weight : i8, + weight : isize, item_type : MenuItemType, } @@ -34,7 +34,7 @@ impl ComponentTrait for MenuItem { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -143,7 +143,7 @@ impl MenuItem { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -155,7 +155,7 @@ impl MenuItem { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } @@ -171,7 +171,7 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, - weight : i8, + weight : isize, items : PageContainer, id : OptIden, classes : Classes, @@ -194,7 +194,7 @@ impl ComponentTrait for Menu { (self.renderable)() } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -254,7 +254,7 @@ impl Menu { self } - pub fn with_weight(mut self, weight: i8) -> Self { + pub fn with_weight(mut self, weight: isize) -> Self { self.alter_weight(weight); self } @@ -281,7 +281,7 @@ impl Menu { self } - pub fn alter_weight(&mut self, weight: i8) -> &mut Self { + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { self.weight = weight; self } diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs index e3173d7f..e90f05be 100644 --- a/pagetop/src/response/page/action.rs +++ b/pagetop/src/response/page/action.rs @@ -10,7 +10,7 @@ pub enum TypeAction { pub struct PageAction { action: TypeAction, - weight: i8, + weight: isize, } impl ActionTrait for PageAction { @@ -21,7 +21,7 @@ impl ActionTrait for PageAction { } } - fn weight(&self) -> i8 { + fn weight(&self) -> isize { self.weight } @@ -38,7 +38,7 @@ impl PageAction { } } - pub fn new_with_weight(action: TypeAction, weight: i8) -> Self { + pub fn new_with_weight(action: TypeAction, weight: isize) -> Self { PageAction { action, weight, diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index 3190b641..ca4a96fc 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -47,12 +47,11 @@ macro_rules! theme_static_files { }}; } -pub(crate) fn partial_type_name(type_name: &'static str, last: u8) -> &'static str { +pub(crate) fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { if last == 0 { return type_name; } let positions: Vec<_> = type_name.rmatch_indices("::").collect(); - let last: usize = last as usize; if positions.len() < last { return type_name; } From 67ddb8d8992219d4e886052c455f7709fcee20f7 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 5 May 2022 21:43:00 +0200 Subject: [PATCH 44/80] =?UTF-8?q?Mejora=20y=20simplifica=20la=20gesti?= =?UTF-8?q?=C3=B3n=20global=20de=20acciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drust/src/main.rs | 2 +- pagetop-admin/src/lib.rs | 10 ++++ pagetop-node/src/lib.rs | 20 +++++-- ...m20220316_000001_create_table_node_type.rs | 8 +-- .../m20220316_000002_create_table_node.rs | 8 +-- ...0220316_000003_create_table_node_access.rs | 8 +-- ...20316_000004_create_table_node_revision.rs | 8 +-- pagetop-user/src/lib.rs | 10 ++-- .../m20220312_000001_create_table_role.rs | 8 +-- ...312_000002_create_table_role_permission.rs | 8 +-- .../m20220312_000003_create_table_user.rs | 8 +-- ...m20220312_000004_create_table_user_role.rs | 8 +-- pagetop/src/api/action/all.rs | 14 +++-- pagetop/src/api/action/definition.rs | 30 ++-------- pagetop/src/api/action/holder.rs | 22 ++++++-- pagetop/src/api/action/mod.rs | 7 ++- pagetop/src/api/component/action.rs | 47 +++++++--------- pagetop/src/api/component/definition.rs | 6 +- pagetop/src/api/component/mod.rs | 6 +- pagetop/src/api/module/all.rs | 13 ++++- pagetop/src/api/module/definition.rs | 9 ++- pagetop/src/app/application.rs | 15 +++-- pagetop/src/db.rs | 17 +++++- pagetop/src/html/classes.rs | 2 +- pagetop/src/prelude.rs | 14 +++-- pagetop/src/response/page/action.rs | 55 +++++++------------ pagetop/src/response/page/mod.rs | 6 +- pagetop/src/response/page/page.rs | 8 +-- pagetop/src/util.rs | 13 +---- 29 files changed, 184 insertions(+), 206 deletions(-) diff --git a/drust/src/main.rs b/drust/src/main.rs index 9da7b124..27bb0886 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -8,5 +8,5 @@ fn bootstrap() { #[actix_web::main] async fn main() -> std::io::Result<()> { - Application::prepare(bootstrap).await?.run()?.await + Application::prepare(UsingBootstrap::Fn(bootstrap)).await?.run()?.await } diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index c07f617b..56d34e1c 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -21,4 +21,14 @@ impl ModuleTrait for Admin { .route("", app::web::get().to(summary::summary)) ); } + + fn actions(&self) -> Vec { + vec![ + action_item!(ActionBeforeRenderPage => before_render_page) + ] + } +} + +fn before_render_page(page: &mut Page) { + page.alter_body_classes("test-admin", ClassesOp::Add); } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index c9e2dcda..1f879f36 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -20,12 +20,18 @@ impl ModuleTrait for Node { cfg.route("/node", app::web::get().to(node)); } - fn migrations(&self) -> Vec> { + fn actions(&self) -> Vec { vec![ - boxed_migration!(m20220316_000001_create_table_node_type), - boxed_migration!(m20220316_000002_create_table_node), - boxed_migration!(m20220316_000003_create_table_node_access), - boxed_migration!(m20220316_000004_create_table_node_revision), + action_item!(ActionBeforeRenderPage => before_render_page, -1) + ] + } + + fn migrations(&self) -> Vec { + vec![ + migration_item!(m20220316_000001_create_table_node_type), + migration_item!(m20220316_000002_create_table_node), + migration_item!(m20220316_000003_create_table_node_access), + migration_item!(m20220316_000004_create_table_node_revision), ] } } @@ -37,3 +43,7 @@ async fn node() -> app::Result { ) .render() } + +fn before_render_page(page: &mut Page) { + page.alter_body_classes("test-node", ClassesOp::Add); +} diff --git a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs index 50117825..9065836a 100644 --- a/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs +++ b/pagetop-node/src/migration/m20220316_000001_create_table_node_type.rs @@ -19,7 +19,7 @@ enum NodeType { // different from the current type name if the locked field is 0. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -82,9 +82,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs index 62e2bda1..1c8d7b12 100644 --- a/pagetop-node/src/migration/m20220316_000002_create_table_node.rs +++ b/pagetop-node/src/migration/m20220316_000002_create_table_node.rs @@ -26,7 +26,7 @@ enum Node { Translate, // A boolean indicating whether this translation page needs to be updated. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -105,9 +105,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs index 140dac2d..3fa19d66 100644 --- a/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs +++ b/pagetop-node/src/migration/m20220316_000003_create_table_node_access.rs @@ -18,7 +18,7 @@ enum NodeAccess { // this node. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -65,9 +65,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs index 0009359f..621628a6 100644 --- a/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs +++ b/pagetop-node/src/migration/m20220316_000004_create_table_node_revision.rs @@ -20,7 +20,7 @@ enum NodeRevision { // be displayed at the top of lists in which it appears. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -83,9 +83,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index bbbf01f3..a36c0e6f 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -19,12 +19,12 @@ impl ModuleTrait for User { cfg.route("/user/login", app::web::get().to(login)); } - fn migrations(&self) -> Vec> { + fn migrations(&self) -> Vec { vec![ - boxed_migration!(m20220312_000001_create_table_role), - boxed_migration!(m20220312_000002_create_table_role_permission), - boxed_migration!(m20220312_000003_create_table_user), - boxed_migration!(m20220312_000004_create_table_user_role), + migration_item!(m20220312_000001_create_table_role), + migration_item!(m20220312_000002_create_table_role_permission), + migration_item!(m20220312_000003_create_table_user), + migration_item!(m20220312_000004_create_table_user_role), ] } } diff --git a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs index 2557453f..649115ac 100644 --- a/pagetop-user/src/migration/m20220312_000001_create_table_role.rs +++ b/pagetop-user/src/migration/m20220312_000001_create_table_role.rs @@ -9,7 +9,7 @@ enum Role { Weight, // The weight of this role in listings and the user interface. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -62,9 +62,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs index 052fed2c..7869f029 100644 --- a/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs +++ b/pagetop-user/src/migration/m20220312_000002_create_table_role_permission.rs @@ -11,7 +11,7 @@ enum RolePermission { #[derive(Iden)] enum Role { Table, Rid, /* ... */ } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -56,9 +56,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs index c060c8a5..ed3d85f7 100644 --- a/pagetop-user/src/migration/m20220312_000003_create_table_user.rs +++ b/pagetop-user/src/migration/m20220312_000003_create_table_user.rs @@ -16,7 +16,7 @@ enum User { Timezone, // User's time zone. } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -77,9 +77,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs index fedcd4be..cae74e3e 100644 --- a/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs +++ b/pagetop-user/src/migration/m20220312_000004_create_table_user_role.rs @@ -14,7 +14,7 @@ enum User { Table, Uid, /* ... */ } #[derive(Iden)] enum Role { Table, Rid, /* ... */ } -pub struct Migration; +pub_migration!(Migration); #[async_trait::async_trait] impl MigrationTrait for Migration { @@ -62,9 +62,3 @@ impl MigrationTrait for Migration { .await } } - -impl MigrationName for Migration { - fn name(&self) -> &str { - module_name!() - } -} diff --git a/pagetop/src/api/action/all.rs b/pagetop/src/api/action/all.rs index e7a4981f..8003d09e 100644 --- a/pagetop/src/api/action/all.rs +++ b/pagetop/src/api/action/all.rs @@ -1,5 +1,5 @@ use crate::Lazy; -use super::{ActionItem, ActionsHolder, ActionTrait}; +use super::{ActionItem, ActionsHolder}; use std::sync::RwLock; use std::collections::HashMap; @@ -9,9 +9,9 @@ static ACTIONS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); -pub fn register_action(action: impl ActionTrait) { +pub fn add_action(action: ActionItem) { let mut hmap = ACTIONS.write().unwrap(); - let action_name = action.type_name(); + let action_name = action.machine_name(); if let Some(actions) = hmap.get_mut(action_name) { actions.add(action); } else { @@ -19,9 +19,11 @@ pub fn register_action(action: impl ActionTrait) { } } -pub fn run_actions(type_name: &'static str, f: F) where F: FnMut(&ActionItem) -> B { - let hmap = ACTIONS.read().unwrap(); - if let Some(actions) = hmap.get(type_name) { +pub fn run_actions(machine_name: &'static str, f: F) +where + F: FnMut(&ActionItem) -> B +{ + if let Some(actions) = ACTIONS.read().unwrap().get(machine_name) { actions.iter_map(f) } } diff --git a/pagetop/src/api/action/definition.rs b/pagetop/src/api/action/definition.rs index e0bab945..1bd554df 100644 --- a/pagetop/src/api/action/definition.rs +++ b/pagetop/src/api/action/definition.rs @@ -1,18 +1,12 @@ -use crate::util; - pub use std::any::Any as AnyAction; -pub trait BaseAction { - fn type_name(&self) -> &'static str; - - fn single_name(&self) -> &'static str; - - fn qualified_name(&self, last: usize) -> &'static str; -} - -pub trait ActionTrait: AnyAction + BaseAction + Send + Sync { +pub trait ActionTrait: AnyAction + Send + Sync { fn new() -> Self where Self: Sized; + fn machine_name(&self) -> &'static str { + std::any::type_name::() + } + fn weight(&self) -> isize { 0 } @@ -20,20 +14,6 @@ pub trait ActionTrait: AnyAction + BaseAction + Send + Sync { fn as_ref_any(&self) -> &dyn AnyAction; } -impl BaseAction for C { - fn type_name(&self) -> &'static str { - std::any::type_name::() - } - - fn single_name(&self) -> &'static str { - util::partial_type_name(std::any::type_name::(), 1) - } - - fn qualified_name(&self, last: usize) -> &'static str { - util::partial_type_name(std::any::type_name::(), last) - } -} - pub fn action_ref(action: &dyn ActionTrait) -> &A { action.as_ref_any().downcast_ref::().unwrap() } diff --git a/pagetop/src/api/action/holder.rs b/pagetop/src/api/action/holder.rs index c7dd3ef3..ab3e2405 100644 --- a/pagetop/src/api/action/holder.rs +++ b/pagetop/src/api/action/holder.rs @@ -4,7 +4,13 @@ use std::sync::{Arc, RwLock}; pub type ActionItem = Box; -#[derive(Clone)] +#[macro_export] +macro_rules! action_item { + ( $action:ident => $f:ident $(, $weight:expr)? ) => {{ + Box::new($action::new().with_action($f)$(.with_weight($weight))?) + }}; +} + pub struct ActionsHolder(Arc>>); impl ActionsHolder { @@ -12,19 +18,23 @@ impl ActionsHolder { ActionsHolder(Arc::new(RwLock::new(Vec::new()))) } - pub fn new_with(action: impl ActionTrait) -> Self { + pub fn new_with(action: ActionItem) -> Self { let mut container = ActionsHolder::new(); container.add(action); container } - pub fn add(&mut self, action: impl ActionTrait) { + pub fn add(&mut self, action: ActionItem) { let mut actions = self.0.write().unwrap(); - actions.push(Box::new(action)); + actions.push(action); actions.sort_by_key(|a| a.weight()); } - pub fn iter_map(&self, f: F) where Self: Sized, F: FnMut(&ActionItem) -> B { - let _ = self.0.read().unwrap().iter().map(f); + pub fn iter_map(&self, f: F) + where + Self: Sized, + F: FnMut(&ActionItem) -> B, + { + let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect(); } } diff --git a/pagetop/src/api/action/mod.rs b/pagetop/src/api/action/mod.rs index e28122e0..78eec705 100644 --- a/pagetop/src/api/action/mod.rs +++ b/pagetop/src/api/action/mod.rs @@ -2,18 +2,21 @@ mod definition; pub use definition::{ ActionTrait, AnyAction, - BaseAction, action_ref, }; mod holder; pub use holder::{ ActionItem, +}; +pub(crate) use holder::{ ActionsHolder, }; mod all; pub use all::{ - register_action, run_actions, }; +pub(crate) use all::{ + add_action, +}; diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs index 6479cc11..34f1cc57 100644 --- a/pagetop/src/api/component/action.rs +++ b/pagetop/src/api/component/action.rs @@ -1,24 +1,25 @@ use crate::api::action::{ActionTrait, AnyAction}; use super::{ComponentTrait, PageAssets}; -pub enum TypeAction { - BeforeRenderComponent(fn(&mut dyn ComponentTrait, &mut PageAssets)), - None, -} +pub const ACTION_BEFORE_RENDER_COMPONENT: &str = "pagetop::render::before_render_component"; -pub struct ComponentAction { - action: TypeAction, +pub struct ActionBeforeRenderComponent { + action: Option, weight: isize, } -impl ActionTrait for ComponentAction { +impl ActionTrait for ActionBeforeRenderComponent { fn new() -> Self { - ComponentAction { - action: TypeAction::None, + ActionBeforeRenderComponent { + action: None, weight: 0, } } + fn machine_name(&self) -> &'static str { + ACTION_BEFORE_RENDER_COMPONENT + } + fn weight(&self) -> isize { self.weight } @@ -28,28 +29,20 @@ impl ActionTrait for ComponentAction { } } -impl ComponentAction { - pub fn new(action: TypeAction) -> Self { - ComponentAction { - action, - weight: 0, - } +impl ActionBeforeRenderComponent { + pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut PageAssets)) -> Self { + self.action = Some(action); + self } - pub fn new_with_weight(action: TypeAction, weight: isize) -> Self { - ComponentAction { - action, - weight, - } + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self } - pub fn before_render_component( - &self, - component: &mut dyn ComponentTrait, - assets: &mut PageAssets) - { - if let TypeAction::BeforeRenderComponent(f) = self.action { - f(component, assets) + pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut PageAssets) { + if let Some(action) = self.action { + action(component, assets) } } } diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index f7c1df43..a6b2ea7c 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -2,7 +2,7 @@ use crate::html::{Markup, html}; use crate::util; use crate::api::action::{action_ref, run_actions}; use super::PageAssets; -use super::action::ComponentAction; +use super::{ACTION_BEFORE_RENDER_COMPONENT, ActionBeforeRenderComponent}; pub use std::any::Any as AnyComponent; @@ -76,8 +76,8 @@ pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut PageAss // Acciones de los módulos antes de renderizar el componente. run_actions( - "", - |a| action_ref::(&**a).before_render_component(component, assets) + ACTION_BEFORE_RENDER_COMPONENT, + |a| action_ref::(&**a).run(component, assets) ); // Acciones del tema antes de renderizar el componente. diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index 7c9482c6..1203d1b2 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -1,4 +1,8 @@ -pub mod action; +mod action; +pub use action::{ + ACTION_BEFORE_RENDER_COMPONENT, + ActionBeforeRenderComponent, +}; mod assets; pub use assets::{ diff --git a/pagetop/src/api/module/all.rs b/pagetop/src/api/module/all.rs index 56e1d6c4..3d5d9a77 100644 --- a/pagetop/src/api/module/all.rs +++ b/pagetop/src/api/module/all.rs @@ -1,4 +1,5 @@ use crate::{Lazy, app, run_now, trace}; +use crate::api::action::add_action; use crate::db::*; use super::ModuleTrait; @@ -37,12 +38,20 @@ pub fn modules(cfg: &mut app::web::ServiceConfig) { } } +pub fn register_actions() { + for m in MODULES.read().unwrap().iter() { + for a in m.actions().into_iter() { + add_action(a); + } + } +} + #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub fn migrations() { +pub fn run_migrations() { run_now({ struct Migrator; impl MigratorTrait for Migrator { - fn migrations() -> Vec> { + fn migrations() -> Vec { let mut migrations = vec![]; for m in MODULES.read().unwrap().iter() { migrations.append(&mut m.migrations()); diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index 837304f3..eb07350c 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -1,7 +1,8 @@ use crate::{app, util}; +use crate::api::action::ActionItem; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -use crate::db; +use crate::db::MigrationItem; pub trait BaseModule { fn type_name(&self) -> &'static str; @@ -25,9 +26,13 @@ pub trait ModuleTrait: BaseModule + Send + Sync { fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { } + fn actions(&self) -> Vec { + vec![] + } + #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] #[allow(unused_variables)] - fn migrations(&self) -> Vec> { + fn migrations(&self) -> Vec { vec![] } diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 1b7564ea..98a49f80 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -9,12 +9,10 @@ pub struct Application { server: app::Server, } -pub fn essence() { - trace::info!("No bootstrap configured"); -} +pub enum UsingBootstrap {Fn(fn()), No} impl Application { - pub async fn prepare(bootstrap: fn()) -> Result { + pub async fn prepare(bootstrap: UsingBootstrap) -> Result { // Rótulo de presentación. app::banner::print_on_startup(); @@ -36,15 +34,20 @@ impl Application { // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); - let _ = &bootstrap(); + if let UsingBootstrap::Fn(bootstrap) = bootstrap { + let _ = &bootstrap(); + } // Registra el módulo de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. module::register_module(&base::module::demopage::Demopage); + // Registra las acciones de todos los módulos. + module::all::register_actions(); + // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - module::all::migrations(); + module::all::run_migrations(); // Prepara el servidor web. let server = app::HttpServer::new(move || { diff --git a/pagetop/src/db.rs b/pagetop/src/db.rs index 4b35bd59..d350043e 100644 --- a/pagetop/src/db.rs +++ b/pagetop/src/db.rs @@ -4,8 +4,23 @@ pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult}; pub use sea_schema::migration::prelude::*; +pub type MigrationItem = Box; + #[macro_export] -macro_rules! boxed_migration { +macro_rules! pub_migration { + ( $migration:ident ) => { + pub struct $migration; + + impl MigrationName for $migration { + fn name(&self) -> &str { + crate::util::partial_type_name(module_path!(), 1) + } + } + }; +} + +#[macro_export] +macro_rules! migration_item { ( $migration_module:ident ) => {{ Box::new(migration::$migration_module::Migration) }}; diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index 225d6537..740d1f89 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -72,7 +72,7 @@ impl Classes { ClassesOp::SetDefault => self.default = classes.to_owned(), } - self.option = Some(concat_string!(self.default, " ", self.added).trim().to_owned()); + self.option = Some(concat_string!(self.default, " ", self.added.trim()).to_owned()); self } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 079deb63..357c31cf 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -4,7 +4,6 @@ pub use crate::{ args, concat_string, - module_name, theme_static_files, }; @@ -14,19 +13,24 @@ pub use crate::localize; pub use crate::html::*; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] -pub use crate::{db, db::*, boxed_migration}; +pub use crate::{ + db, + db::*, + pub_migration, + migration_item, +}; -pub use crate::api::{ +pub use crate::{action_item, api::{ action::*, component::*, module::*, theme::*, -}; +}}; pub use crate::response::page::*; pub use crate::app; -pub use crate::app::application::{Application, essence}; +pub use crate::app::application::{Application, UsingBootstrap}; pub use crate::base::component::*; diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs index e90f05be..d47b5ca6 100644 --- a/pagetop/src/response/page/action.rs +++ b/pagetop/src/response/page/action.rs @@ -1,26 +1,25 @@ use crate::api::action::{ActionTrait, AnyAction}; -use crate::api::component::{ComponentTrait, PageAssets}; use super::Page; -pub enum TypeAction { - BeforeRenderPage(fn(&mut Page)), - BeforeRenderComponent(fn(&mut dyn ComponentTrait, &mut PageAssets)), - None, -} +pub const ACTION_BEFORE_RENDER_PAGE: &str = "pagetop::render::before_render_page"; -pub struct PageAction { - action: TypeAction, +pub struct ActionBeforeRenderPage { + action: Option, weight: isize, } -impl ActionTrait for PageAction { +impl ActionTrait for ActionBeforeRenderPage { fn new() -> Self { - PageAction { - action: TypeAction::None, + ActionBeforeRenderPage { + action: None, weight: 0, } } + fn machine_name(&self) -> &'static str { + ACTION_BEFORE_RENDER_PAGE + } + fn weight(&self) -> isize { self.weight } @@ -30,34 +29,20 @@ impl ActionTrait for PageAction { } } -impl PageAction { - pub fn new(action: TypeAction) -> Self { - PageAction { - action, - weight: 0, - } +impl ActionBeforeRenderPage { + pub fn with_action(mut self, action: fn(&mut Page)) -> Self { + self.action = Some(action); + self } - pub fn new_with_weight(action: TypeAction, weight: isize) -> Self { - PageAction { - action, - weight, - } + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self } - pub fn before_render_page(&self, page: &mut Page) { - if let TypeAction::BeforeRenderPage(f) = self.action { - f(page) - } - } - - pub fn before_render_component( - &self, - component: &mut dyn ComponentTrait, - assets: &mut PageAssets) - { - if let TypeAction::BeforeRenderComponent(f) = self.action { - f(component, assets) + pub fn run(&self, page: &mut Page) { + if let Some(action) = self.action { + action(page) } } } diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 097bde8b..3d8194f2 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -1,4 +1,8 @@ -pub mod action; +mod action; +pub use action::{ + ACTION_BEFORE_RENDER_PAGE, + ActionBeforeRenderPage, +}; mod page; pub use page::Page; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index b52566a8..13944810 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -6,7 +6,7 @@ use crate::api::component::*; use std::collections::HashMap; -use super::action::PageAction; +use super::{ACTION_BEFORE_RENDER_PAGE, ActionBeforeRenderPage}; static DEFAULT_LANGUAGE: Lazy> = Lazy::new(|| { let language = SETTINGS.app.language[..2].to_lowercase(); @@ -151,10 +151,10 @@ impl<'a> Page<'a> { // Page RENDER. pub fn render(&mut self) -> app::Result { - // Acciones de los módulos antes de renderizar el tema. + // Acciones de los módulos antes de renderizar la página. run_actions( - "", - |a| action_ref::(&**a).before_render_page(self) + ACTION_BEFORE_RENDER_PAGE, + |a| action_ref::(&**a).run(self) ); // Acciones del tema antes de renderizar la página. diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index ca4a96fc..f87b67fc 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -18,17 +18,6 @@ macro_rules! args { }}; } -#[macro_export] -macro_rules! module_name { - () => {{ - let name = module_path!(); - match name.rfind("::") { - Some(position) => &name[(position + 2)..], - None => name - } - }}; -} - #[macro_export] macro_rules! theme_static_files { ( $cfg:ident, $dir:expr ) => {{ @@ -47,7 +36,7 @@ macro_rules! theme_static_files { }}; } -pub(crate) fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { +pub fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { if last == 0 { return type_name; } From d8b2e3089cc15e7bf1295d0b020442b14c010ad7 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 5 May 2022 21:45:36 +0200 Subject: [PATCH 45/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 003bde82..36215a52 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.9" +version = "0.0.10" edition = "2021" authors = [ From c2b69fa539f14fff213702294bec0937d7fd2641 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 5 May 2022 23:23:47 +0200 Subject: [PATCH 46/80] =?UTF-8?q?Actualiza=20nomenclatura=20en=20c=C3=B3di?= =?UTF-8?q?go?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-admin/src/lib.rs | 2 +- pagetop-node/src/lib.rs | 2 +- pagetop-user/src/lib.rs | 26 ++++++++++++------------- pagetop/src/api/component/container.rs | 4 ++-- pagetop/src/api/component/definition.rs | 4 ++-- pagetop/src/api/module/all.rs | 2 +- pagetop/src/api/module/definition.rs | 2 +- pagetop/src/base/module/demopage/mod.rs | 2 +- pagetop/src/response/page/page.rs | 3 +-- 9 files changed, 23 insertions(+), 24 deletions(-) diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index 56d34e1c..5ca91531 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -15,7 +15,7 @@ impl ModuleTrait for Admin { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { cfg.service( app::web::scope("/admin") .route("", app::web::get().to(summary::summary)) diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index 1f879f36..3f8bff18 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -16,7 +16,7 @@ impl ModuleTrait for Node { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { cfg.route("/node", app::web::get().to(node)); } diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index a36c0e6f..557ecdac 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -15,7 +15,7 @@ impl ModuleTrait for User { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { cfg.route("/user/login", app::web::get().to(login)); } @@ -29,6 +29,18 @@ impl ModuleTrait for User { } } +async fn login() -> app::Result { + Page::new() + .with_title( + "Identificación del usuario" + ) + .add_to("content", Container::new() + .with_id("welcome") + .add(form_login()) + ) + .render() +} + fn form_login() -> Form { Form::new() .with_id("user-login") @@ -47,15 +59,3 @@ fn form_login() -> Form { ) .add(form::Button::submit(l("login").as_str())) } - -async fn login() -> app::Result { - Page::new() - .with_title( - "Identificación del usuario" - ) - .add_to("content", Container::new() - .with_id("welcome") - .add(form_login()) - ) - .render() -} diff --git a/pagetop/src/api/component/container.rs b/pagetop/src/api/component/container.rs index 5ca41056..5008a94d 100644 --- a/pagetop/src/api/component/container.rs +++ b/pagetop/src/api/component/container.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use super::{PageAssets, ComponentTrait, render_component}; +use super::{ComponentTrait, PageAssets}; use std::sync::{Arc, RwLock}; @@ -26,7 +26,7 @@ impl PageContainer { components.sort_by_key(|c| c.read().unwrap().weight()); html! { @for c in components.iter() { - (render_component(&mut *c.write().unwrap(), assets)) + (super::render_component(&mut *c.write().unwrap(), assets)) } } } diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index a6b2ea7c..a7e6decb 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -1,8 +1,8 @@ use crate::html::{Markup, html}; -use crate::util; use crate::api::action::{action_ref, run_actions}; -use super::PageAssets; +use crate::util; use super::{ACTION_BEFORE_RENDER_COMPONENT, ActionBeforeRenderComponent}; +use super::PageAssets; pub use std::any::Any as AnyComponent; diff --git a/pagetop/src/api/module/all.rs b/pagetop/src/api/module/all.rs index 3d5d9a77..6c7948de 100644 --- a/pagetop/src/api/module/all.rs +++ b/pagetop/src/api/module/all.rs @@ -34,7 +34,7 @@ fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { pub fn modules(cfg: &mut app::web::ServiceConfig) { for m in MODULES.read().unwrap().iter() { - m.configure_module(cfg); + m.configure_service(cfg); } } diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index eb07350c..d1c213e3 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -23,7 +23,7 @@ pub trait ModuleTrait: BaseModule + Send + Sync { } #[allow(unused_variables)] - fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { } fn actions(&self) -> Vec { diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 34ac79b7..55ed6d56 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -13,7 +13,7 @@ impl ModuleTrait for Demopage { Some(l("module_description")) } - fn configure_module(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { cfg.route("/", app::web::get().to(demo)); } } diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 13944810..206224ec 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -3,11 +3,10 @@ use crate::config::SETTINGS; use crate::html::*; use crate::api::action::{action_ref, run_actions}; use crate::api::component::*; +use super::{ACTION_BEFORE_RENDER_PAGE, ActionBeforeRenderPage}; use std::collections::HashMap; -use super::{ACTION_BEFORE_RENDER_PAGE, ActionBeforeRenderPage}; - static DEFAULT_LANGUAGE: Lazy> = Lazy::new(|| { let language = SETTINGS.app.language[..2].to_lowercase(); if !language.is_empty() { From d53408c6b60cfe8d381b370be3e2ae197f90c148 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 6 May 2022 00:27:21 +0200 Subject: [PATCH 47/80] Modifica PageContainer para ser ComponentsHolder --- pagetop/src/api/action/mod.rs | 2 +- pagetop/src/api/component/all.rs | 8 ++++---- pagetop/src/api/component/{container.rs => holder.rs} | 8 ++++---- pagetop/src/api/component/mod.rs | 10 +++++++--- pagetop/src/base/component/block.rs | 6 +++--- pagetop/src/base/component/container.rs | 6 +++--- pagetop/src/base/component/form/form.rs | 6 +++--- pagetop/src/base/component/grid/column.rs | 6 +++--- pagetop/src/base/component/grid/row.rs | 6 +++--- pagetop/src/base/component/menu.rs | 6 +++--- pagetop/src/response/page/page.rs | 4 ++-- 11 files changed, 36 insertions(+), 32 deletions(-) rename pagetop/src/api/component/{container.rs => holder.rs} (80%) diff --git a/pagetop/src/api/action/mod.rs b/pagetop/src/api/action/mod.rs index 78eec705..59310a8a 100644 --- a/pagetop/src/api/action/mod.rs +++ b/pagetop/src/api/action/mod.rs @@ -9,7 +9,7 @@ mod holder; pub use holder::{ ActionItem, }; -pub(crate) use holder::{ +use holder::{ ActionsHolder, }; diff --git a/pagetop/src/api/component/all.rs b/pagetop/src/api/component/all.rs index 6ba66752..82573f59 100644 --- a/pagetop/src/api/component/all.rs +++ b/pagetop/src/api/component/all.rs @@ -1,10 +1,10 @@ use crate::Lazy; -use super::{ComponentTrait, PageContainer}; +use super::{ComponentsHolder, ComponentTrait}; use std::sync::RwLock; use std::collections::HashMap; -static COMPONENTS: Lazy>> = Lazy::new(|| { +static COMPONENTS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); @@ -13,10 +13,10 @@ pub fn add_component_to(region: &'static str, component: impl ComponentTrait) { if let Some(regions) = hmap.get_mut(region) { regions.add(component); } else { - hmap.insert(region, PageContainer::new_with(component)); + hmap.insert(region, ComponentsHolder::new_with(component)); } } -pub fn common_components() -> HashMap<&'static str, PageContainer> { +pub fn common_components() -> HashMap<&'static str, ComponentsHolder> { COMPONENTS.read().unwrap().clone() } diff --git a/pagetop/src/api/component/container.rs b/pagetop/src/api/component/holder.rs similarity index 80% rename from pagetop/src/api/component/container.rs rename to pagetop/src/api/component/holder.rs index 5008a94d..b3fa54e8 100644 --- a/pagetop/src/api/component/container.rs +++ b/pagetop/src/api/component/holder.rs @@ -4,15 +4,15 @@ use super::{ComponentTrait, PageAssets}; use std::sync::{Arc, RwLock}; #[derive(Clone)] -pub struct PageContainer(Vec>>); +pub struct ComponentsHolder(Vec>>); -impl PageContainer { +impl ComponentsHolder { pub fn new() -> Self { - PageContainer(Vec::new()) + ComponentsHolder(Vec::new()) } pub fn new_with(component: impl ComponentTrait) -> Self { - let mut container = PageContainer::new(); + let mut container = ComponentsHolder::new(); container.add(component); container } diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index 1203d1b2..3faac016 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -20,10 +20,14 @@ pub use definition::{ component_ref, component_mut, }; -use definition::render_component; +use definition::{ + render_component, +}; -mod container; -pub use container::PageContainer; +mod holder; +pub use holder::{ + ComponentsHolder, +}; mod all; pub use all::{ diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index b1407d60..d0b4ad7a 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -5,7 +5,7 @@ pub const TYPENAME_BLOCK: &str = "pagetop::base::component::block::Block"; pub struct Block { renderable: fn() -> bool, weight : isize, - components: PageContainer, + components: ComponentsHolder, title : OptAttr, id : OptIden, classes : Classes, @@ -17,7 +17,7 @@ impl ComponentTrait for Block { Block { renderable: render_always, weight : 0, - components: PageContainer::new(), + components: ComponentsHolder::new(), title : OptAttr::new(), id : OptIden::new(), classes : Classes::new_with_default("block"), @@ -66,7 +66,7 @@ impl Block { self } - pub fn components(&self) -> &PageContainer { + pub fn components(&self) -> &ComponentsHolder { &self.components } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index dbc58ce6..5c64b14e 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -7,7 +7,7 @@ pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable : fn() -> bool, weight : isize, - components : PageContainer, + components : ComponentsHolder, container : ContainerType, id : OptIden, classes : Classes, @@ -20,7 +20,7 @@ impl ComponentTrait for Container { Container { renderable : render_always, weight : 0, - components : PageContainer::new(), + components : ComponentsHolder::new(), container : ContainerType::Wrapper, id : OptIden::new(), classes : Classes::new_with_default("container"), @@ -116,7 +116,7 @@ impl Container { self } - pub fn components(&self) -> &PageContainer { + pub fn components(&self) -> &ComponentsHolder { &self.components } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 0ddb99eb..2f4fa609 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -7,7 +7,7 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : isize, - elements : PageContainer, + elements : ComponentsHolder, action : OptAttr, charset : OptAttr, method : FormMethod, @@ -21,7 +21,7 @@ impl ComponentTrait for Form { Form { renderable: render_always, weight : 0, - elements : PageContainer::new(), + elements : ComponentsHolder::new(), action : OptAttr::new(), charset : OptAttr::new_with_value("UTF-8"), method : FormMethod::Post, @@ -75,7 +75,7 @@ impl Form { self } - pub fn elements(&self) -> &PageContainer { + pub fn elements(&self) -> &ComponentsHolder { &self.elements } diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index add535e3..ca22ad37 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -5,7 +5,7 @@ pub const TYPENAME_COLUMN: &str = "pagetop::base::component::grid::column::Colum pub struct Column { renderable: fn() -> bool, weight : isize, - components: PageContainer, + components: ComponentsHolder, id : OptIden, classes : Classes, template : String, @@ -16,7 +16,7 @@ impl ComponentTrait for Column { Column { renderable: render_always, weight : 0, - components: PageContainer::new(), + components: ComponentsHolder::new(), id : OptIden::new(), classes : Classes::new_with_default("col"), template : "default".to_owned(), @@ -57,7 +57,7 @@ impl Column { self } - pub fn components(&self) -> &PageContainer { + pub fn components(&self) -> &ComponentsHolder { &self.components } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index d8a8858a..b9692015 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -5,7 +5,7 @@ pub const TYPENAME_ROW: &str = "pagetop::base::component::grid::row::Row"; pub struct Row { renderable: fn() -> bool, weight : isize, - columns : PageContainer, + columns : ComponentsHolder, id : OptIden, classes : Classes, template : String, @@ -16,7 +16,7 @@ impl ComponentTrait for Row { Row { renderable: render_always, weight : 0, - columns : PageContainer::new(), + columns : ComponentsHolder::new(), id : OptIden::new(), classes : Classes::new_with_default("row"), template : "default".to_owned(), @@ -57,7 +57,7 @@ impl Row { self } - pub fn columns(&self) -> &PageContainer { + pub fn columns(&self) -> &ComponentsHolder { &self.columns } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index f0bd2a40..a152b9ec 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -172,7 +172,7 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, weight : isize, - items : PageContainer, + items : ComponentsHolder, id : OptIden, classes : Classes, template : String, @@ -183,7 +183,7 @@ impl ComponentTrait for Menu { Menu { renderable: render_always, weight : 0, - items : PageContainer::new(), + items : ComponentsHolder::new(), id : OptIden::new(), classes : Classes::new_with_default("sm sm-clean"), template : "default".to_owned(), @@ -243,7 +243,7 @@ impl Menu { self } - pub fn items(&self) -> &PageContainer { + pub fn items(&self) -> &ComponentsHolder { &self.items } diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 206224ec..3669f649 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -42,7 +42,7 @@ pub struct Page<'a> { title : OptAttr, description : OptAttr, assets : PageAssets, - regions : HashMap<&'a str, PageContainer>, + regions : HashMap<&'a str, ComponentsHolder>, body_classes: Classes, template : String, } @@ -102,7 +102,7 @@ impl<'a> Page<'a> { if let Some(regions) = self.regions.get_mut(region) { regions.add(component); } else { - self.regions.insert(region, PageContainer::new_with(component)); + self.regions.insert(region, ComponentsHolder::new_with(component)); } self } From fce106af7ae0e8ce4aacb057a9dce3e502bbcb7e Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 6 May 2022 00:55:47 +0200 Subject: [PATCH 48/80] Modifica PageAssets para ser simplemente Assets --- pagetop/src/api/component/action.rs | 8 ++++---- pagetop/src/api/component/assets.rs | 6 +++--- pagetop/src/api/component/definition.rs | 8 ++++---- pagetop/src/api/component/holder.rs | 4 ++-- pagetop/src/api/component/mod.rs | 2 +- pagetop/src/api/theme/definition.rs | 6 +++--- pagetop/src/base/component/block.rs | 2 +- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 2 +- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 4 ++-- pagetop/src/base/component/grid/column.rs | 2 +- pagetop/src/base/component/grid/row.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 4 ++-- pagetop/src/base/theme/bulmix/mod.rs | 2 +- pagetop/src/response/page/page.rs | 6 +++--- 20 files changed, 35 insertions(+), 35 deletions(-) diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs index 34f1cc57..9e372570 100644 --- a/pagetop/src/api/component/action.rs +++ b/pagetop/src/api/component/action.rs @@ -1,10 +1,10 @@ use crate::api::action::{ActionTrait, AnyAction}; -use super::{ComponentTrait, PageAssets}; +use super::{Assets, ComponentTrait}; pub const ACTION_BEFORE_RENDER_COMPONENT: &str = "pagetop::render::before_render_component"; pub struct ActionBeforeRenderComponent { - action: Option, + action: Option, weight: isize, } @@ -30,7 +30,7 @@ impl ActionTrait for ActionBeforeRenderComponent { } impl ActionBeforeRenderComponent { - pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut PageAssets)) -> Self { + pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { self.action = Some(action); self } @@ -40,7 +40,7 @@ impl ActionBeforeRenderComponent { self } - pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut PageAssets) { + pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) { if let Some(action) = self.action { action(component, assets) } diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/api/component/assets.rs index c7faf1bc..4801ada2 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -173,7 +173,7 @@ impl JavaScript { // Page assets. -pub struct PageAssets { +pub struct Assets { theme : &'static dyn ThemeTrait, favicon : Option, metadata : Vec<(String, String)>, @@ -183,9 +183,9 @@ pub struct PageAssets { id_counter : usize, } -impl PageAssets { +impl Assets { pub fn new() -> Self { - PageAssets { + Assets { theme : *DEFAULT_THEME, favicon : None, metadata : Vec::new(), diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index a7e6decb..61893243 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -2,7 +2,7 @@ use crate::html::{Markup, html}; use crate::api::action::{action_ref, run_actions}; use crate::util; use super::{ACTION_BEFORE_RENDER_COMPONENT, ActionBeforeRenderComponent}; -use super::PageAssets; +use super::Assets; pub use std::any::Any as AnyComponent; @@ -35,11 +35,11 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { } #[allow(unused_variables)] - fn before_render(&mut self, assets: &mut PageAssets) { + fn before_render(&mut self, assets: &mut Assets) { } #[allow(unused_variables)] - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { html! {} } @@ -70,7 +70,7 @@ pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { component.as_mut_any().downcast_mut::().unwrap() } -pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut PageAssets) -> Markup { +pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) -> Markup { // Acciones del componente antes de renderizar. component.before_render(assets); diff --git a/pagetop/src/api/component/holder.rs b/pagetop/src/api/component/holder.rs index b3fa54e8..51b67736 100644 --- a/pagetop/src/api/component/holder.rs +++ b/pagetop/src/api/component/holder.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use super::{ComponentTrait, PageAssets}; +use super::{Assets, ComponentTrait}; use std::sync::{Arc, RwLock}; @@ -21,7 +21,7 @@ impl ComponentsHolder { self.0.push(Arc::new(RwLock::new(component))); } - pub fn render(&self, assets: &mut PageAssets) -> Markup { + pub fn render(&self, assets: &mut Assets) -> Markup { let mut components = self.0.clone(); components.sort_by_key(|c| c.read().unwrap().weight()); html! { diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index 3faac016..a119089f 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -6,10 +6,10 @@ pub use action::{ mod assets; pub use assets::{ + Assets, Favicon, StyleSheet, JavaScript, JSMode, - PageAssets, }; mod definition; diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/api/theme/definition.rs index 08d913e6..b5a12243 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -1,7 +1,7 @@ use crate::{app, concat_string}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::api::component::{ComponentTrait, Favicon, PageAssets}; +use crate::api::component::{Assets, ComponentTrait, Favicon}; use crate::response::page::Page; use crate::base::component::Chunck; use crate::util; @@ -88,7 +88,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn before_render_component( &self, component: &mut dyn ComponentTrait, - assets: &mut PageAssets + assets: &mut Assets ) { /* Cómo usarlo: @@ -107,7 +107,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn render_component( &self, component: &dyn ComponentTrait, - assets: &mut PageAssets + assets: &mut Assets ) -> Option { None /* diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index d0b4ad7a..df209ea9 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -33,7 +33,7 @@ impl ComponentTrait for Block { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { let id = assets.serial_id(self.single_name(), self.id()); html! { div id=(id) class=[self.classes()] { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index 26666344..a772af1d 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -27,7 +27,7 @@ impl ComponentTrait for Chunck { self.weight } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { html! { (*self.html()) } } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 5c64b14e..dd2508ad 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -37,7 +37,7 @@ impl ComponentTrait for Container { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { match self.container_type() { ContainerType::Header => html! { header id=[self.id()] class=[self.classes()] { diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 16720106..47f2e9ca 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -40,7 +40,7 @@ impl ComponentTrait for Button { self.weight } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { let button_type = match self.button_type() { ButtonType::Button => "button", ButtonType::Reset => "reset", diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 741ac450..e9741120 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -48,7 +48,7 @@ impl ComponentTrait for Date { self.weight } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("edit-", name)), None => None, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 2f4fa609..70a9caf6 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -39,7 +39,7 @@ impl ComponentTrait for Form { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { let method = match self.method() { FormMethod::Get => None, FormMethod::Post => Some("post".to_owned()) diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 4df5fd4f..c837d0a8 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -21,7 +21,7 @@ impl ComponentTrait for Hidden { self.weight } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("value-", name)), _ => None diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 573ddebf..a7168097 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -58,14 +58,14 @@ impl ComponentTrait for Input { self.weight } - fn before_render(&mut self, _: &mut PageAssets) { + fn before_render(&mut self, _: &mut Assets) { if let Some(name) = self.name() { let class = concat_string!("form-item-", name); self.alter_classes(class.as_str(), ClassesOp::AddFirst); } } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { let type_input = match self.input_type() { InputType::Email => "email", InputType::Password => "password", diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index ca22ad37..8199c986 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -31,7 +31,7 @@ impl ComponentTrait for Column { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { html! { div id=[self.id()] class=[self.classes()] { (self.components().render(assets)) diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index b9692015..a366cf7a 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -31,7 +31,7 @@ impl ComponentTrait for Row { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { html! { div id=[self.id()] class=[self.classes()] { (self.columns().render(assets)) diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index ee92215a..efb647c2 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -31,7 +31,7 @@ impl ComponentTrait for Image { self.weight } - fn default_render(&self, _: &mut PageAssets) -> Markup { + fn default_render(&self, _: &mut Assets) -> Markup { html! { img src=[self.source()] diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index a152b9ec..9b416daf 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -38,7 +38,7 @@ impl ComponentTrait for MenuItem { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { match self.item_type() { MenuItemType::Label(label) => html! { li class="label" { a href="#" { (label) } } @@ -198,7 +198,7 @@ impl ComponentTrait for Menu { self.weight } - fn default_render(&self, assets: &mut PageAssets) -> Markup { + fn default_render(&self, assets: &mut Assets) -> Markup { assets .add_stylesheet(StyleSheet::source( "/theme/menu/css/menu.css?ver=1.1.1" diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index a4b194f4..1a36fe7d 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -27,7 +27,7 @@ impl ThemeTrait for Bulmix { fn before_render_component( &self, component: &mut dyn ComponentTrait, - _assets: &mut PageAssets + _assets: &mut Assets ) { match component.type_name() { grid::TYPENAME_ROW => { diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 3669f649..0fc9c627 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -41,7 +41,7 @@ pub struct Page<'a> { direction : OptAttr, title : OptAttr, description : OptAttr, - assets : PageAssets, + assets : Assets, regions : HashMap<&'a str, ComponentsHolder>, body_classes: Classes, template : String, @@ -61,7 +61,7 @@ impl<'a> Page<'a> { }, title : OptAttr::new(), description : OptAttr::new(), - assets : PageAssets::new(), + assets : Assets::new(), regions : common_components(), body_classes: Classes::new_with_default("body"), template : "default".to_owned(), @@ -135,7 +135,7 @@ impl<'a> Page<'a> { self.description.option() } - pub fn assets(&mut self) -> &mut PageAssets { + pub fn assets(&mut self) -> &mut Assets { &mut self.assets } From a6d39202d49b18a10f2c67672adc12da095d02cd Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 15:15:14 +0200 Subject: [PATCH 49/80] =?UTF-8?q?Modifica=20y=20simplifica=20identificaci?= =?UTF-8?q?=C3=B3n=20de=20acciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/api/action/all.rs | 13 +++++++------ pagetop/src/api/action/definition.rs | 4 ---- pagetop/src/api/component/action.rs | 6 ------ pagetop/src/api/component/definition.rs | 7 +++---- pagetop/src/api/component/mod.rs | 5 +---- pagetop/src/api/mod.rs | 2 ++ pagetop/src/prelude.rs | 1 + pagetop/src/response/page/action.rs | 6 ------ pagetop/src/response/page/mod.rs | 5 +---- pagetop/src/response/page/page.rs | 6 +++--- 10 files changed, 18 insertions(+), 37 deletions(-) diff --git a/pagetop/src/api/action/all.rs b/pagetop/src/api/action/all.rs index 8003d09e..4e301777 100644 --- a/pagetop/src/api/action/all.rs +++ b/pagetop/src/api/action/all.rs @@ -1,29 +1,30 @@ use crate::Lazy; +use crate::api::TypeId; use super::{ActionItem, ActionsHolder}; use std::sync::RwLock; use std::collections::HashMap; // Registered actions. -static ACTIONS: Lazy>> = Lazy::new(|| { +static ACTIONS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); pub fn add_action(action: ActionItem) { let mut hmap = ACTIONS.write().unwrap(); - let action_name = action.machine_name(); - if let Some(actions) = hmap.get_mut(action_name) { + let action_id = action.type_id(); + if let Some(actions) = hmap.get_mut(&action_id) { actions.add(action); } else { - hmap.insert(action_name, ActionsHolder::new_with(action)); + hmap.insert(action_id, ActionsHolder::new_with(action)); } } -pub fn run_actions(machine_name: &'static str, f: F) +pub fn run_actions(action_id: TypeId, f: F) where F: FnMut(&ActionItem) -> B { - if let Some(actions) = ACTIONS.read().unwrap().get(machine_name) { + if let Some(actions) = ACTIONS.read().unwrap().get(&action_id) { actions.iter_map(f) } } diff --git a/pagetop/src/api/action/definition.rs b/pagetop/src/api/action/definition.rs index 1bd554df..9acb1258 100644 --- a/pagetop/src/api/action/definition.rs +++ b/pagetop/src/api/action/definition.rs @@ -3,10 +3,6 @@ pub use std::any::Any as AnyAction; pub trait ActionTrait: AnyAction + Send + Sync { fn new() -> Self where Self: Sized; - fn machine_name(&self) -> &'static str { - std::any::type_name::() - } - fn weight(&self) -> isize { 0 } diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs index 9e372570..d4e1f460 100644 --- a/pagetop/src/api/component/action.rs +++ b/pagetop/src/api/component/action.rs @@ -1,8 +1,6 @@ use crate::api::action::{ActionTrait, AnyAction}; use super::{Assets, ComponentTrait}; -pub const ACTION_BEFORE_RENDER_COMPONENT: &str = "pagetop::render::before_render_component"; - pub struct ActionBeforeRenderComponent { action: Option, weight: isize, @@ -16,10 +14,6 @@ impl ActionTrait for ActionBeforeRenderComponent { } } - fn machine_name(&self) -> &'static str { - ACTION_BEFORE_RENDER_COMPONENT - } - fn weight(&self) -> isize { self.weight } diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index 61893243..687b4eae 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -1,8 +1,7 @@ use crate::html::{Markup, html}; -use crate::api::action::{action_ref, run_actions}; +use crate::api::{TypeId, action::{action_ref, run_actions}}; use crate::util; -use super::{ACTION_BEFORE_RENDER_COMPONENT, ActionBeforeRenderComponent}; -use super::Assets; +use super::{ActionBeforeRenderComponent, Assets}; pub use std::any::Any as AnyComponent; @@ -76,7 +75,7 @@ pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) // Acciones de los módulos antes de renderizar el componente. run_actions( - ACTION_BEFORE_RENDER_COMPONENT, + TypeId::of::(), |a| action_ref::(&**a).run(component, assets) ); diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index a119089f..10a894b9 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -1,8 +1,5 @@ mod action; -pub use action::{ - ACTION_BEFORE_RENDER_COMPONENT, - ActionBeforeRenderComponent, -}; +pub use action::ActionBeforeRenderComponent; mod assets; pub use assets::{ diff --git a/pagetop/src/api/mod.rs b/pagetop/src/api/mod.rs index b69ec91b..8d84af05 100644 --- a/pagetop/src/api/mod.rs +++ b/pagetop/src/api/mod.rs @@ -1,3 +1,5 @@ +pub use std::any::TypeId; + pub mod action; // API to define functions that alter the behavior of PageTop core. pub mod component; // API para crear nuevos componentes. pub mod module; // API para añadir módulos con nuevas funcionalidades. diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 357c31cf..a20d1563 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -21,6 +21,7 @@ pub use crate::{ }; pub use crate::{action_item, api::{ + TypeId, action::*, component::*, module::*, diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs index d47b5ca6..7fe35a7f 100644 --- a/pagetop/src/response/page/action.rs +++ b/pagetop/src/response/page/action.rs @@ -1,8 +1,6 @@ use crate::api::action::{ActionTrait, AnyAction}; use super::Page; -pub const ACTION_BEFORE_RENDER_PAGE: &str = "pagetop::render::before_render_page"; - pub struct ActionBeforeRenderPage { action: Option, weight: isize, @@ -16,10 +14,6 @@ impl ActionTrait for ActionBeforeRenderPage { } } - fn machine_name(&self) -> &'static str { - ACTION_BEFORE_RENDER_PAGE - } - fn weight(&self) -> isize { self.weight } diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 3d8194f2..30f95d72 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -1,8 +1,5 @@ mod action; -pub use action::{ - ACTION_BEFORE_RENDER_PAGE, - ActionBeforeRenderPage, -}; +pub use action::ActionBeforeRenderPage; mod page; pub use page::Page; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 0fc9c627..99a81cb3 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,9 +1,9 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::api::action::{action_ref, run_actions}; +use crate::api::{TypeId, action::{action_ref, run_actions}}; use crate::api::component::*; -use super::{ACTION_BEFORE_RENDER_PAGE, ActionBeforeRenderPage}; +use super::ActionBeforeRenderPage; use std::collections::HashMap; @@ -152,7 +152,7 @@ impl<'a> Page<'a> { pub fn render(&mut self) -> app::Result { // Acciones de los módulos antes de renderizar la página. run_actions( - ACTION_BEFORE_RENDER_PAGE, + TypeId::of::(), |a| action_ref::(&**a).run(self) ); From cbfe374eb5052a7080f0e547333fed5f7cdb8aff Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 15:29:38 +0200 Subject: [PATCH 50/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- pagetop/src/api/component/assets.rs | 60 ++++++++++++++--------------- pagetop/src/api/component/mod.rs | 2 +- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 36215a52..1888cacc 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.10" +version = "0.0.11" edition = "2021" authors = [ diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/api/component/assets.rs index 4801ada2..30a6e4b1 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -97,36 +97,6 @@ impl Favicon { } } -// StyleSheet. - -pub struct StyleSheet { - source: &'static str, - weight: isize, -} -impl StyleSheet { - pub fn source(s: &'static str) -> Self { - StyleSheet { - source: s, - weight: 0, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn weight(self) -> isize { - self.weight - } - - fn render(&self) -> Markup { - html! { - link rel="stylesheet" href=(self.source); - } - } -} - // JavaScript. #[derive(PartialEq)] @@ -171,6 +141,36 @@ impl JavaScript { } } +// StyleSheet. + +pub struct StyleSheet { + source: &'static str, + weight: isize, +} +impl StyleSheet { + pub fn source(s: &'static str) -> Self { + StyleSheet { + source: s, + weight: 0, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn weight(self) -> isize { + self.weight + } + + fn render(&self) -> Markup { + html! { + link rel="stylesheet" href=(self.source); + } + } +} + // Page assets. pub struct Assets { diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index 10a894b9..fe21f1ea 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -5,8 +5,8 @@ mod assets; pub use assets::{ Assets, Favicon, - StyleSheet, JavaScript, JSMode, + StyleSheet, }; mod definition; From e8226daa4bba215261ee4806e4f849016aa05dc9 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 18:56:55 +0200 Subject: [PATCH 51/80] =?UTF-8?q?Corrige=20asignaci=C3=B3n=20de=20clases?= =?UTF-8?q?=20para=20evitar=20espacios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/html/classes.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index 740d1f89..aa629aaf 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -34,7 +34,9 @@ impl Classes { pub fn alter(&mut self, classes: &str, op: ClassesOp) -> &Self { let classes = classes.trim(); match op { - ClassesOp::Add => self.added.push_str(concat_string!(" ", classes).as_str()), + ClassesOp::Add => { + self.added = concat_string!(self.added, " ", classes).trim().to_owned() + }, ClassesOp::AddAfter(class) => { let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); @@ -54,7 +56,9 @@ impl Classes { self.added = v_added.join(" "); }, - ClassesOp::AddFirst => self.added = concat_string!(classes, " ", self.added), + ClassesOp::AddFirst => { + self.added = concat_string!(classes, " ", self.added).trim().to_owned() + }, ClassesOp::Replace(class) => { let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); @@ -72,7 +76,7 @@ impl Classes { ClassesOp::SetDefault => self.default = classes.to_owned(), } - self.option = Some(concat_string!(self.default, " ", self.added.trim()).to_owned()); + self.option = Some(concat_string!(self.default, " ", self.added).trim().to_owned()); self } From 68a347382df76842a573dc39589f4eeaaa0c6164 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 23:16:00 +0200 Subject: [PATCH 52/80] Modifica identificador por handler() --- pagetop-admin/src/lib.rs | 6 ++++ pagetop-node/src/lib.rs | 6 ++++ pagetop-user/src/lib.rs | 6 ++++ pagetop/src/api/action/all.rs | 16 ++++------ pagetop/src/api/action/definition.rs | 2 ++ pagetop/src/api/component/action.rs | 14 ++++++--- pagetop/src/api/component/definition.rs | 38 ++++++----------------- pagetop/src/api/component/mod.rs | 6 ++-- pagetop/src/api/mod.rs | 2 -- pagetop/src/api/module/all.rs | 6 ++-- pagetop/src/api/module/definition.rs | 31 ++++-------------- pagetop/src/api/module/mod.rs | 9 ++---- pagetop/src/api/theme/all.rs | 4 +-- pagetop/src/api/theme/definition.rs | 36 +++++---------------- pagetop/src/api/theme/mod.rs | 5 +-- pagetop/src/base/component/block.rs | 8 +++-- pagetop/src/base/component/chunck.rs | 6 +++- pagetop/src/base/component/container.rs | 6 +++- pagetop/src/base/component/form/button.rs | 6 +++- pagetop/src/base/component/form/date.rs | 6 +++- pagetop/src/base/component/form/form.rs | 6 +++- pagetop/src/base/component/form/hidden.rs | 6 +++- pagetop/src/base/component/form/input.rs | 6 +++- pagetop/src/base/component/form/mod.rs | 10 +++--- pagetop/src/base/component/grid/column.rs | 6 +++- pagetop/src/base/component/grid/mod.rs | 4 +-- pagetop/src/base/component/grid/row.rs | 6 +++- pagetop/src/base/component/image.rs | 6 +++- pagetop/src/base/component/menu.rs | 14 +++++++-- pagetop/src/base/component/mod.rs | 12 +++---- pagetop/src/base/module/demopage/mod.rs | 6 ++++ pagetop/src/base/theme/aliner/mod.rs | 6 ++++ pagetop/src/base/theme/bootsier/mod.rs | 6 ++++ pagetop/src/base/theme/bulmix/mod.rs | 12 +++++-- pagetop/src/base/theme/minimal/mod.rs | 5 +++ pagetop/src/prelude.rs | 1 - pagetop/src/response/page/action.rs | 6 ++++ pagetop/src/response/page/mod.rs | 5 ++- pagetop/src/response/page/page.rs | 6 ++-- pagetop/src/util.rs | 4 +++ 40 files changed, 200 insertions(+), 152 deletions(-) diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index 5ca91531..d05138b4 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -1,5 +1,7 @@ use pagetop::prelude::*; +pub const ADMIN_MODULE: &str = "pagetop-admin::module::admin"; + localize!("src/locales"); mod summary; @@ -7,6 +9,10 @@ mod summary; pub struct Admin; impl ModuleTrait for Admin { + fn handler(&self) -> &'static str { + ADMIN_MODULE + } + fn name(&self) -> String { l("module_name") } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index 3f8bff18..98af01bd 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -1,5 +1,7 @@ use pagetop::prelude::*; +pub const NODE_MODULE: &str = "pagetop-node::module::node"; + localize!("src/locales"); //mod entity; @@ -8,6 +10,10 @@ mod migration; pub struct Node; impl ModuleTrait for Node { + fn handler(&self) -> &'static str { + NODE_MODULE + } + fn name(&self) -> String { l("module_name") } diff --git a/pagetop-user/src/lib.rs b/pagetop-user/src/lib.rs index 557ecdac..8003e707 100644 --- a/pagetop-user/src/lib.rs +++ b/pagetop-user/src/lib.rs @@ -1,5 +1,7 @@ use pagetop::prelude::*; +pub const USER_MODULE: &str = "pagetop-user::module::user"; + localize!("src/locales"); mod migration; @@ -7,6 +9,10 @@ mod migration; pub struct User; impl ModuleTrait for User { + fn handler(&self) -> &'static str { + USER_MODULE + } + fn name(&self) -> String { l("module_name") } diff --git a/pagetop/src/api/action/all.rs b/pagetop/src/api/action/all.rs index 4e301777..cb9bfb8d 100644 --- a/pagetop/src/api/action/all.rs +++ b/pagetop/src/api/action/all.rs @@ -1,30 +1,26 @@ use crate::Lazy; -use crate::api::TypeId; use super::{ActionItem, ActionsHolder}; use std::sync::RwLock; use std::collections::HashMap; // Registered actions. -static ACTIONS: Lazy>> = Lazy::new(|| { +static ACTIONS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); pub fn add_action(action: ActionItem) { let mut hmap = ACTIONS.write().unwrap(); - let action_id = action.type_id(); - if let Some(actions) = hmap.get_mut(&action_id) { + let action_handler = action.handler(); + if let Some(actions) = hmap.get_mut(action_handler) { actions.add(action); } else { - hmap.insert(action_id, ActionsHolder::new_with(action)); + hmap.insert(action_handler, ActionsHolder::new_with(action)); } } -pub fn run_actions(action_id: TypeId, f: F) -where - F: FnMut(&ActionItem) -> B -{ - if let Some(actions) = ACTIONS.read().unwrap().get(&action_id) { +pub fn run_actions(action_handler: &str, f: F) where F: FnMut(&ActionItem) -> B { + if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) { actions.iter_map(f) } } diff --git a/pagetop/src/api/action/definition.rs b/pagetop/src/api/action/definition.rs index 9acb1258..1c950686 100644 --- a/pagetop/src/api/action/definition.rs +++ b/pagetop/src/api/action/definition.rs @@ -3,6 +3,8 @@ pub use std::any::Any as AnyAction; pub trait ActionTrait: AnyAction + Send + Sync { fn new() -> Self where Self: Sized; + fn handler(&self) -> &'static str; + fn weight(&self) -> isize { 0 } diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs index d4e1f460..243646cc 100644 --- a/pagetop/src/api/component/action.rs +++ b/pagetop/src/api/component/action.rs @@ -1,19 +1,25 @@ use crate::api::action::{ActionTrait, AnyAction}; use super::{Assets, ComponentTrait}; -pub struct ActionBeforeRenderComponent { +pub const BEFORE_RENDER_COMPONENT_ACTION: &str = "pagetop::action::before_render_component"; + +pub struct BeforeRenderComponentAction { action: Option, weight: isize, } -impl ActionTrait for ActionBeforeRenderComponent { +impl ActionTrait for BeforeRenderComponentAction { fn new() -> Self { - ActionBeforeRenderComponent { + BeforeRenderComponentAction { action: None, weight: 0, } } + fn handler(&self) -> &'static str { + BEFORE_RENDER_COMPONENT_ACTION + } + fn weight(&self) -> isize { self.weight } @@ -23,7 +29,7 @@ impl ActionTrait for ActionBeforeRenderComponent { } } -impl ActionBeforeRenderComponent { +impl BeforeRenderComponentAction { pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { self.action = Some(action); self diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index 687b4eae..a807a36f 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -1,24 +1,18 @@ use crate::html::{Markup, html}; -use crate::api::{TypeId, action::{action_ref, run_actions}}; +use crate::api::action::{action_ref, run_actions}; use crate::util; -use super::{ActionBeforeRenderComponent, Assets}; +use super::{BEFORE_RENDER_COMPONENT_ACTION, BeforeRenderComponentAction}; +use super::Assets; pub use std::any::Any as AnyComponent; -pub trait BaseComponent { - fn type_name(&self) -> &'static str; - - fn single_name(&self) -> &'static str; - - fn qualified_name(&self, last: usize) -> &'static str; -} - -pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { - +pub trait ComponentTrait: AnyComponent + Send + Sync { fn new() -> Self where Self: Sized; + fn handler(&self) -> &'static str; + fn name(&self) -> String { - self.single_name().to_owned() + util::single_type_name::().to_owned() } fn description(&self) -> Option { @@ -47,20 +41,6 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { fn as_mut_any(&mut self) -> &mut dyn AnyComponent; } -impl BaseComponent for C { - fn type_name(&self) -> &'static str { - std::any::type_name::() - } - - fn single_name(&self) -> &'static str { - util::partial_type_name(std::any::type_name::(), 1) - } - - fn qualified_name(&self, last: usize) -> &'static str { - util::partial_type_name(std::any::type_name::(), last) - } -} - pub fn component_ref(component: &dyn ComponentTrait) -> &C { component.as_ref_any().downcast_ref::().unwrap() } @@ -75,8 +55,8 @@ pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) // Acciones de los módulos antes de renderizar el componente. run_actions( - TypeId::of::(), - |a| action_ref::(&**a).run(component, assets) + BEFORE_RENDER_COMPONENT_ACTION, + |a| action_ref::(&**a).run(component, assets) ); // Acciones del tema antes de renderizar el componente. diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index fe21f1ea..95044f52 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -1,5 +1,8 @@ mod action; -pub use action::ActionBeforeRenderComponent; +pub use action::{ + BEFORE_RENDER_COMPONENT_ACTION, + BeforeRenderComponentAction, +}; mod assets; pub use assets::{ @@ -12,7 +15,6 @@ pub use assets::{ mod definition; pub use definition::{ AnyComponent, - BaseComponent, ComponentTrait, component_ref, component_mut, diff --git a/pagetop/src/api/mod.rs b/pagetop/src/api/mod.rs index 8d84af05..b69ec91b 100644 --- a/pagetop/src/api/mod.rs +++ b/pagetop/src/api/mod.rs @@ -1,5 +1,3 @@ -pub use std::any::TypeId; - pub mod action; // API to define functions that alter the behavior of PageTop core. pub mod component; // API para crear nuevos componentes. pub mod module; // API para añadir módulos con nuevas funcionalidades. diff --git a/pagetop/src/api/module/all.rs b/pagetop/src/api/module/all.rs index 6c7948de..1bb6ea7d 100644 --- a/pagetop/src/api/module/all.rs +++ b/pagetop/src/api/module/all.rs @@ -18,9 +18,9 @@ pub fn register_module(module: &'static dyn ModuleTrait) { } fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { - if !MODULES.read().unwrap().iter().any(|m| m.type_name() == module.type_name()) { - if !list.iter().any(|m| m.type_name() == module.type_name()) { - trace::debug!("Registering \"{}\" module", module.single_name()); + if !MODULES.read().unwrap().iter().any(|m| m.handler() == module.handler()) { + if !list.iter().any(|m| m.handler() == module.handler()) { + trace::debug!("Register module: \"{}\"", module.name()); list.push(module); let mut dependencies = module.dependencies(); diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index d1c213e3..7ee26e5d 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -1,21 +1,16 @@ -use crate::{app, util}; +use crate::app; use crate::api::action::ActionItem; +use crate::util; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db::MigrationItem; -pub trait BaseModule { - fn type_name(&self) -> &'static str; - - fn single_name(&self) -> &'static str; - - fn qualified_name(&self, last: usize) -> &'static str; -} - /// Los módulos deben implementar este *trait*. -pub trait ModuleTrait: BaseModule + Send + Sync { +pub trait ModuleTrait: Send + Sync { + fn handler(&self) -> &'static str; + fn name(&self) -> String { - self.single_name().to_owned() + util::single_type_name::().to_owned() } fn description(&self) -> Option { @@ -40,17 +35,3 @@ pub trait ModuleTrait: BaseModule + Send + Sync { vec![] } } - -impl BaseModule for M { - fn type_name(&self) -> &'static str { - std::any::type_name::() - } - - fn single_name(&self) -> &'static str { - util::partial_type_name(std::any::type_name::(), 1) - } - - fn qualified_name(&self, last: usize) -> &'static str { - util::partial_type_name(std::any::type_name::(), last) - } -} diff --git a/pagetop/src/api/module/mod.rs b/pagetop/src/api/module/mod.rs index d1addefe..b4a97393 100644 --- a/pagetop/src/api/module/mod.rs +++ b/pagetop/src/api/module/mod.rs @@ -1,10 +1,5 @@ mod definition; -pub use definition::{ - BaseModule, - ModuleTrait, -}; +pub use definition::ModuleTrait; pub(crate) mod all; -pub use all::{ - register_module, -}; +pub use all::register_module; diff --git a/pagetop/src/api/theme/all.rs b/pagetop/src/api/theme/all.rs index 12d96338..b1e47307 100644 --- a/pagetop/src/api/theme/all.rs +++ b/pagetop/src/api/theme/all.rs @@ -12,8 +12,8 @@ static THEMES: Lazy>> = Lazy::new(|| { pub fn register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); - if !themes.iter().any(|t| t.name() == theme.name()) { - trace::debug!("Registering \"{}\" theme", theme.single_name()); + if !themes.iter().any(|t| t.handler() == theme.handler()) { + trace::debug!("Register theme: \"{}\"", theme.name()); themes.push(theme); } } diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/api/theme/definition.rs index b5a12243..6bfa63d5 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -6,18 +6,12 @@ use crate::response::page::Page; use crate::base::component::Chunck; use crate::util; -pub trait BaseTheme { - fn type_name(&self) -> &'static str; - - fn single_name(&self) -> &'static str; - - fn qualified_name(&self, last: usize) -> &'static str; -} - /// Los temas deben implementar este "trait". -pub trait ThemeTrait: BaseTheme + Send + Sync { +pub trait ThemeTrait: Send + Sync { + fn handler(&self) -> &'static str; + fn name(&self) -> String { - self.single_name().to_owned() + util::single_type_name::().to_owned() } fn description(&self) -> Option { @@ -93,8 +87,8 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { /* Cómo usarlo: - match component.single_name() { - "Block" => { + match component.handler() { + BLOCK_COMPONENT => { let block = component_mut::(component); block.alter_title("New title"); }, @@ -113,8 +107,8 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { /* Cómo usarlo: - match component.single_name() { - "Block" => { + match component.handler() { + BLOCK_COMPONENT => { let block = component_ref::(component); match block.template() { "default" => Some(block_default(block)), @@ -137,17 +131,3 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { .render() } } - -impl BaseTheme for T { - fn type_name(&self) -> &'static str { - std::any::type_name::() - } - - fn single_name(&self) -> &'static str { - util::partial_type_name(std::any::type_name::(), 1) - } - - fn qualified_name(&self, last: usize) -> &'static str { - util::partial_type_name(std::any::type_name::(), last) - } -} diff --git a/pagetop/src/api/theme/mod.rs b/pagetop/src/api/theme/mod.rs index f76d1fe3..4456189e 100644 --- a/pagetop/src/api/theme/mod.rs +++ b/pagetop/src/api/theme/mod.rs @@ -1,8 +1,5 @@ mod definition; -pub use definition::{ - BaseTheme, - ThemeTrait, -}; +pub use definition::ThemeTrait; pub(crate) mod all; pub use all::{ diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index df209ea9..dafe4497 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_BLOCK: &str = "pagetop::base::component::block::Block"; +pub const BLOCK_COMPONENT: &str = "pagetop::component::block"; pub struct Block { renderable: fn() -> bool, @@ -25,6 +25,10 @@ impl ComponentTrait for Block { } } + fn handler(&self) -> &'static str { + BLOCK_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } @@ -34,7 +38,7 @@ impl ComponentTrait for Block { } fn default_render(&self, assets: &mut Assets) -> Markup { - let id = assets.serial_id(self.single_name(), self.id()); + let id = assets.serial_id("block", self.id()); html! { div id=(id) class=[self.classes()] { @match self.title() { diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index a772af1d..c7d8a978 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_CHUNCK: &str = "pagetop::base::component::chunck::Chunck"; +pub const CHUNCK_COMPONENT: &str = "pagetop::component::chunck"; pub struct Chunck { renderable: fn() -> bool, @@ -19,6 +19,10 @@ impl ComponentTrait for Chunck { } } + fn handler(&self) -> &'static str { + CHUNCK_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index dd2508ad..e275f255 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_CONTAINER: &str = "pagetop::base::component::container::Container"; +pub const CONTAINER_COMPONENT: &str = "pagetop::component::container"; pub enum ContainerType { Header, Footer, Main, Section, Wrapper } @@ -29,6 +29,10 @@ impl ComponentTrait for Container { } } + fn handler(&self) -> &'static str { + CONTAINER_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index 47f2e9ca..fc7fe620 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_BUTTON: &str = "pagetop::base::component::form::button::Button"; +pub const BUTTON_COMPONENT: &str = "pagetop::component::form::button"; pub enum ButtonType {Button, Reset, Submit} @@ -32,6 +32,10 @@ impl ComponentTrait for Button { .with_classes("form-button", ClassesOp::AddFirst) } + fn handler(&self) -> &'static str { + BUTTON_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index e9741120..eeb1d7aa 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_DATE: &str = "pagetop::base::component::form::date::Date"; +pub const DATE_COMPONENT: &str = "pagetop::component::form::date"; pub struct Date { renderable : fn() -> bool, @@ -40,6 +40,10 @@ impl ComponentTrait for Date { .with_classes("form-type-date", ClassesOp::AddFirst) } + fn handler(&self) -> &'static str { + DATE_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 70a9caf6..dcf209b0 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_FORM: &str = "pagetop::base::component::form::form::Form"; +pub const FORM_COMPONENT: &str = "pagetop::component::form"; pub enum FormMethod {Get, Post} @@ -31,6 +31,10 @@ impl ComponentTrait for Form { } } + fn handler(&self) -> &'static str { + FORM_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index c837d0a8..c8d86131 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_HIDDEN: &str = "pagetop::base::component::form::hidden::Hidden"; +pub const HIDDEN_COMPONENT: &str = "pagetop::component::form::hidden"; pub struct Hidden { weight: isize, @@ -17,6 +17,10 @@ impl ComponentTrait for Hidden { } } + fn handler(&self) -> &'static str { + HIDDEN_COMPONENT + } + fn weight(&self) -> isize { self.weight } diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index a7168097..d1614aa3 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_INPUT: &str = "pagetop::base::component::form::input::Input"; +pub const INPUT_COMPONENT: &str = "pagetop::component::form::input"; pub enum InputType {Email, Password, Search, Telephone, Textfield, Url} @@ -50,6 +50,10 @@ impl ComponentTrait for Input { .with_classes("form-type-textfield", ClassesOp::AddFirst) } + fn handler(&self) -> &'static str { + INPUT_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/base/component/form/mod.rs index d8df6d2d..4e35a9d4 100644 --- a/pagetop/src/base/component/form/mod.rs +++ b/pagetop/src/base/component/form/mod.rs @@ -1,21 +1,21 @@ mod form; pub use form::{ - TYPENAME_FORM, Form, FormMethod + FORM_COMPONENT, Form, FormMethod }; mod input; pub use input::{ - TYPENAME_INPUT, Input, InputType + INPUT_COMPONENT, Input, InputType }; mod hidden; pub use hidden::{ - TYPENAME_HIDDEN, Hidden + HIDDEN_COMPONENT, Hidden }; mod date; pub use date::{ - TYPENAME_DATE, Date + DATE_COMPONENT, Date }; mod button; pub use button::{ - TYPENAME_BUTTON, Button, ButtonType + BUTTON_COMPONENT, Button, ButtonType }; diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 8199c986..a69edce7 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_COLUMN: &str = "pagetop::base::component::grid::column::Column"; +pub const COLUMN_COMPONENT: &str = "pagetop::component::grid::column"; pub struct Column { renderable: fn() -> bool, @@ -23,6 +23,10 @@ impl ComponentTrait for Column { } } + fn handler(&self) -> &'static str { + COLUMN_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/grid/mod.rs b/pagetop/src/base/component/grid/mod.rs index e63ea7cd..4fd8936b 100644 --- a/pagetop/src/base/component/grid/mod.rs +++ b/pagetop/src/base/component/grid/mod.rs @@ -1,8 +1,8 @@ mod row; pub use row::{ - TYPENAME_ROW, Row + ROW_COMPONENT, Row }; mod column; pub use column::{ - TYPENAME_COLUMN, Column + COLUMN_COMPONENT, Column }; diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index a366cf7a..05fae1cf 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_ROW: &str = "pagetop::base::component::grid::row::Row"; +pub const ROW_COMPONENT: &str = "pagetop::component::grid::row"; pub struct Row { renderable: fn() -> bool, @@ -23,6 +23,10 @@ impl ComponentTrait for Row { } } + fn handler(&self) -> &'static str { + ROW_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index efb647c2..300cafc2 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -pub const TYPENAME_IMAGE: &str = "pagetop::base::component::image::Image"; +pub const IMAGE_COMPONENT: &str = "pagetop::component::image"; pub struct Image { renderable: fn() -> bool, @@ -23,6 +23,10 @@ impl ComponentTrait for Image { } } + fn handler(&self) -> &'static str { + IMAGE_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 9b416daf..0434b90f 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,7 +1,7 @@ use crate::prelude::*; -pub const TYPENAME_MENU: &str = "pagetop::base::component::menu::Menu"; -pub const TYPENAME_MENUITEM: &str = "pagetop::base::component::menu::MenuItem"; +pub const MENU_COMPONENT: &str = "pagetop::component::menu"; +pub const MENUITEM_COMPONENT: &str = "pagetop::component::menu"; pub enum MenuItemType { Label(String), @@ -30,6 +30,10 @@ impl ComponentTrait for MenuItem { } } + fn handler(&self) -> &'static str { + MENUITEM_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } @@ -190,6 +194,10 @@ impl ComponentTrait for Menu { } } + fn handler(&self) -> &'static str { + MENU_COMPONENT + } + fn is_renderable(&self) -> bool { (self.renderable)() } @@ -211,7 +219,7 @@ impl ComponentTrait for Menu { )) .add_jquery(); - let id = assets.serial_id(self.single_name(), self.id()); + let id = assets.serial_id("menu", self.id()); html! { ul id=(id) class=[self.classes()] { (self.items().render(assets)) diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index 032fd625..14759dc8 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -1,28 +1,28 @@ mod container; pub use container::{ - TYPENAME_CONTAINER, Container, ContainerType + CONTAINER_COMPONENT, Container, ContainerType }; pub mod grid; mod chunck; pub use chunck::{ - TYPENAME_CHUNCK, Chunck + CHUNCK_COMPONENT, Chunck }; mod block; pub use block::{ - TYPENAME_BLOCK, Block + BLOCK_COMPONENT, Block }; mod image; pub use image::{ - TYPENAME_IMAGE, Image + IMAGE_COMPONENT, Image }; mod menu; pub use menu::{ - TYPENAME_MENU, TYPENAME_MENUITEM, Menu, MenuItem, MenuItemType + MENU_COMPONENT, MENUITEM_COMPONENT, Menu, MenuItem, MenuItemType }; pub mod form; pub use form::{ - TYPENAME_FORM, Form, FormMethod + FORM_COMPONENT, Form, FormMethod }; diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 55ed6d56..343b00a0 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -1,10 +1,16 @@ use crate::prelude::*; +pub const DEMOPAGE_MODULE: &str = "pagetop::module::demopage"; + localize!("src/base/module/demopage/locales"); pub struct Demopage; impl ModuleTrait for Demopage { + fn handler(&self) -> &'static str { + DEMOPAGE_MODULE + } + fn name(&self) -> String { l("module_name") } diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index 6936a019..f3c90f9b 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -1,10 +1,16 @@ use crate::prelude::*; +pub const ALINER_THEME: &str = "pagetop::theme::aliner"; + include!(concat!(env!("OUT_DIR"), "/aliner.rs")); pub struct Aliner; impl ThemeTrait for Aliner { + fn handler(&self) -> &'static str { + ALINER_THEME + } + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/aliner"); } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index 0445356b..a8be7118 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +pub const BOOTSIER_THEME: &str = "pagetop::theme::bootsier"; + include!(concat!(env!("OUT_DIR"), "/bootsier.rs")); localize!("src/base/theme/bootsier/locales"); @@ -7,6 +9,10 @@ localize!("src/base/theme/bootsier/locales"); pub struct Bootsier; impl ThemeTrait for Bootsier { + fn handler(&self) -> &'static str { + BOOTSIER_THEME + } + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bootsier"); } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 1a36fe7d..477dbbf7 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -1,10 +1,16 @@ use crate::prelude::*; +pub const BULMIX_THEME: &str = "pagetop::theme::bulmix"; + include!(concat!(env!("OUT_DIR"), "/bulmix.rs")); pub struct Bulmix; impl ThemeTrait for Bulmix { + fn handler(&self) -> &'static str { + BULMIX_THEME + } + fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bulmix"); } @@ -29,12 +35,12 @@ impl ThemeTrait for Bulmix { component: &mut dyn ComponentTrait, _assets: &mut Assets ) { - match component.type_name() { - grid::TYPENAME_ROW => { + match component.handler() { + grid::ROW_COMPONENT => { let row = component_mut::(component); row.alter_classes("columns", ClassesOp::SetDefault); }, - grid::TYPENAME_COLUMN => { + grid::COLUMN_COMPONENT => { let col = component_mut::(component); col.alter_classes("column", ClassesOp::SetDefault); }, diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal/mod.rs index d2124fb6..e86e1719 100644 --- a/pagetop/src/base/theme/minimal/mod.rs +++ b/pagetop/src/base/theme/minimal/mod.rs @@ -1,6 +1,11 @@ use crate::prelude::*; +pub const MINIMAL_THEME: &str = "pagetop::theme::minimal"; + pub struct Minimal; impl ThemeTrait for Minimal { + fn handler(&self) -> &'static str { + MINIMAL_THEME + } } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index a20d1563..357c31cf 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -21,7 +21,6 @@ pub use crate::{ }; pub use crate::{action_item, api::{ - TypeId, action::*, component::*, module::*, diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs index 7fe35a7f..7869987c 100644 --- a/pagetop/src/response/page/action.rs +++ b/pagetop/src/response/page/action.rs @@ -1,6 +1,8 @@ use crate::api::action::{ActionTrait, AnyAction}; use super::Page; +pub const BEFORE_RENDER_PAGE_ACTION: &str = "pagetop::action::before_render_page"; + pub struct ActionBeforeRenderPage { action: Option, weight: isize, @@ -14,6 +16,10 @@ impl ActionTrait for ActionBeforeRenderPage { } } + fn handler(&self) -> &'static str { + BEFORE_RENDER_PAGE_ACTION + } + fn weight(&self) -> isize { self.weight } diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index 30f95d72..e08e55f0 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -1,5 +1,8 @@ mod action; -pub use action::ActionBeforeRenderPage; +pub use action::{ + BEFORE_RENDER_PAGE_ACTION, + ActionBeforeRenderPage, +}; mod page; pub use page::Page; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index 99a81cb3..a4fc741b 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,9 +1,9 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::api::{TypeId, action::{action_ref, run_actions}}; +use crate::api::action::{action_ref, run_actions}; use crate::api::component::*; -use super::ActionBeforeRenderPage; +use super::{BEFORE_RENDER_PAGE_ACTION, ActionBeforeRenderPage}; use std::collections::HashMap; @@ -152,7 +152,7 @@ impl<'a> Page<'a> { pub fn render(&mut self) -> app::Result { // Acciones de los módulos antes de renderizar la página. run_actions( - TypeId::of::(), + BEFORE_RENDER_PAGE_ACTION, |a| action_ref::(&**a).run(self) ); diff --git a/pagetop/src/util.rs b/pagetop/src/util.rs index f87b67fc..f4f683bf 100644 --- a/pagetop/src/util.rs +++ b/pagetop/src/util.rs @@ -46,3 +46,7 @@ pub fn partial_type_name(type_name: &'static str, last: usize) -> &'static str { } &type_name[(positions[last - 1].0 + 2)..] } + +pub fn single_type_name() -> &'static str { + partial_type_name(std::any::type_name::(), 1) +} From 5e8a1f75fd1883d61be908a7c21129baf5f59001 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 23:25:54 +0200 Subject: [PATCH 53/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- pagetop/src/api/action/mod.rs | 16 ++++------------ pagetop/src/api/component/mod.rs | 8 ++------ pagetop/src/lib.rs | 2 +- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 1888cacc..912c3477 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.11" +version = "0.0.12" edition = "2021" authors = [ diff --git a/pagetop/src/api/action/mod.rs b/pagetop/src/api/action/mod.rs index 59310a8a..53e32f8d 100644 --- a/pagetop/src/api/action/mod.rs +++ b/pagetop/src/api/action/mod.rs @@ -6,17 +6,9 @@ pub use definition::{ }; mod holder; -pub use holder::{ - ActionItem, -}; -use holder::{ - ActionsHolder, -}; +pub use holder::ActionItem; +use holder::ActionsHolder; mod all; -pub use all::{ - run_actions, -}; -pub(crate) use all::{ - add_action, -}; +pub use all::run_actions; +pub(crate) use all::add_action; diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/api/component/mod.rs index 95044f52..a8ee3c4d 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/api/component/mod.rs @@ -19,14 +19,10 @@ pub use definition::{ component_ref, component_mut, }; -use definition::{ - render_component, -}; +use definition::render_component; mod holder; -pub use holder::{ - ComponentsHolder, -}; +pub use holder::ComponentsHolder; mod all; pub use all::{ diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index fd843285..2c298184 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,8 +1,8 @@ // External. +pub use once_cell::sync::Lazy; pub use concat_string::concat_string; pub use doc_comment::doc_comment; -pub use once_cell::sync::Lazy; // Local. From 3366a6acdc3870b793efc31930796aab1003e30b Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 7 May 2022 23:51:04 +0200 Subject: [PATCH 54/80] =?UTF-8?q?Actualiza=20textos=20y=20formato=20del=20?= =?UTF-8?q?c=C3=B3digo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/api/action/holder.rs | 6 +----- pagetop/src/api/component/assets.rs | 9 ++++++--- pagetop/src/api/component/definition.rs | 2 +- pagetop/src/api/mod.rs | 6 +++--- pagetop/src/api/module/definition.rs | 3 +-- pagetop/src/api/theme/definition.rs | 3 +-- pagetop/src/base/component/block.rs | 2 +- pagetop/src/base/component/menu.rs | 2 +- pagetop/src/lib.rs | 4 ++-- 9 files changed, 17 insertions(+), 20 deletions(-) diff --git a/pagetop/src/api/action/holder.rs b/pagetop/src/api/action/holder.rs index ab3e2405..7009e103 100644 --- a/pagetop/src/api/action/holder.rs +++ b/pagetop/src/api/action/holder.rs @@ -30,11 +30,7 @@ impl ActionsHolder { actions.sort_by_key(|a| a.weight()); } - pub fn iter_map(&self, f: F) - where - Self: Sized, - F: FnMut(&ActionItem) -> B, - { + pub fn iter_map(&self, f: F) where Self: Sized, F: FnMut(&ActionItem) -> B { let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect(); } } diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/api/component/assets.rs index 30a6e4b1..aa05ebd5 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -1,4 +1,4 @@ -use crate::{Lazy, base, concat_string}; +use crate::{Lazy, base, concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; use crate::api::theme::*; @@ -281,11 +281,14 @@ impl Assets { // Assets EXTRAS. - pub fn serial_id(&mut self, prefix: &str, id: &Option) -> String { + pub fn required_id(&mut self, id: &Option) -> String { match id { Some(id) => id.to_string(), None => { - let prefix = prefix.trim().replace(" ", "_").to_lowercase(); + let prefix = util::single_type_name::() + .trim() + .replace(" ", "_") + .to_lowercase(); let prefix = if prefix.is_empty() { "prefix".to_owned() } else { diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/api/component/definition.rs index a807a36f..4381b08e 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/api/component/definition.rs @@ -1,6 +1,6 @@ +use crate::util; use crate::html::{Markup, html}; use crate::api::action::{action_ref, run_actions}; -use crate::util; use super::{BEFORE_RENDER_COMPONENT_ACTION, BeforeRenderComponentAction}; use super::Assets; diff --git a/pagetop/src/api/mod.rs b/pagetop/src/api/mod.rs index b69ec91b..ff5daff9 100644 --- a/pagetop/src/api/mod.rs +++ b/pagetop/src/api/mod.rs @@ -1,4 +1,4 @@ pub mod action; // API to define functions that alter the behavior of PageTop core. -pub mod component; // API para crear nuevos componentes. -pub mod module; // API para añadir módulos con nuevas funcionalidades. -pub mod theme; // API para crear temas. +pub mod component; // API to build new components. +pub mod module; // API to add new features with modules. +pub mod theme; // API to create themes. diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index 7ee26e5d..1deb7d80 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -1,6 +1,5 @@ -use crate::app; +use crate::{app, util}; use crate::api::action::ActionItem; -use crate::util; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db::MigrationItem; diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/api/theme/definition.rs index 6bfa63d5..e063b355 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -1,10 +1,9 @@ -use crate::{app, concat_string}; +use crate::{app, concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::api::component::{Assets, ComponentTrait, Favicon}; use crate::response::page::Page; use crate::base::component::Chunck; -use crate::util; /// Los temas deben implementar este "trait". pub trait ThemeTrait: Send + Sync { diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index dafe4497..4f120434 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -38,7 +38,7 @@ impl ComponentTrait for Block { } fn default_render(&self, assets: &mut Assets) -> Markup { - let id = assets.serial_id("block", self.id()); + let id = assets.required_id::(self.id()); html! { div id=(id) class=[self.classes()] { @match self.title() { diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 0434b90f..450bc92e 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -219,7 +219,7 @@ impl ComponentTrait for Menu { )) .add_jquery(); - let id = assets.serial_id("menu", self.id()); + let id = assets.required_id::(self.id()); html! { ul id=(id) class=[self.classes()] { (self.items().render(assets)) diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 2c298184..20a25229 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -1,4 +1,4 @@ -// External. +// External re-exports. pub use once_cell::sync::Lazy; pub use concat_string::concat_string; @@ -25,6 +25,6 @@ pub mod app; // Aplicación y servidor web. pub mod base; // Base de componentes, módulos y temas. pub mod util; // Macros y funciones útiles. -// Re-exports. +// Internal re-exports. pub mod prelude; From af9afca77796bab0c1cad3a32db556b1c01c53bd Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 8 May 2022 01:02:07 +0200 Subject: [PATCH 55/80] =?UTF-8?q?Modifica=20identificaci=C3=B3n=20de=20m?= =?UTF-8?q?=C3=B3dulos=20y=20temas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drust/src/main.rs | 6 +++--- pagetop/src/api/component/assets.rs | 4 ++-- pagetop/src/api/module/all.rs | 4 ++-- pagetop/src/api/module/definition.rs | 18 ++++++++++++++---- pagetop/src/api/module/mod.rs | 9 +++++++-- pagetop/src/api/theme/all.rs | 6 +++--- pagetop/src/api/theme/definition.rs | 14 ++++++++++++-- pagetop/src/api/theme/mod.rs | 7 +++++-- pagetop/src/app/application.rs | 2 +- 9 files changed, 49 insertions(+), 21 deletions(-) diff --git a/drust/src/main.rs b/drust/src/main.rs index 27bb0886..6b610c8b 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,9 +1,9 @@ use pagetop::prelude::*; fn bootstrap() { - register_module(&pagetop_admin::Admin); - register_module(&pagetop_user::User); - register_module(&pagetop_node::Node); + include_module(&pagetop_admin::Admin); + include_module(&pagetop_user::User); + include_module(&pagetop_node::Node); } #[actix_web::main] diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/api/component/assets.rs index aa05ebd5..1ff78d23 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/api/component/assets.rs @@ -4,7 +4,7 @@ use crate::html::{Markup, PreEscaped, html}; use crate::api::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - match theme_by_name(&SETTINGS.app.theme) { + match theme_by_single_name(&SETTINGS.app.theme) { Some(theme) => theme, None => &base::theme::bootsier::Bootsier, } @@ -197,7 +197,7 @@ impl Assets { } pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.theme = theme_by_name(theme_name).unwrap_or(*DEFAULT_THEME); + self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); self } diff --git a/pagetop/src/api/module/all.rs b/pagetop/src/api/module/all.rs index 1bb6ea7d..778dba2e 100644 --- a/pagetop/src/api/module/all.rs +++ b/pagetop/src/api/module/all.rs @@ -10,7 +10,7 @@ static MODULES: Lazy>> = Lazy::new(|| { RwLock::new(Vec::new()) }); -pub fn register_module(module: &'static dyn ModuleTrait) { +pub fn include_module(module: &'static dyn ModuleTrait) { let mut list: Vec<&dyn ModuleTrait> = Vec::new(); add_to(&mut list, module); list.reverse(); @@ -20,7 +20,7 @@ pub fn register_module(module: &'static dyn ModuleTrait) { fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { if !MODULES.read().unwrap().iter().any(|m| m.handler() == module.handler()) { if !list.iter().any(|m| m.handler() == module.handler()) { - trace::debug!("Register module: \"{}\"", module.name()); + trace::debug!("Including module \"{}\"", module.single_name()); list.push(module); let mut dependencies = module.dependencies(); diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/api/module/definition.rs index 1deb7d80..e457e3f0 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/api/module/definition.rs @@ -4,18 +4,26 @@ use crate::api::action::ActionItem; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db::MigrationItem; +pub trait BaseModule { + fn single_name(&self) -> &'static str; +} + /// Los módulos deben implementar este *trait*. -pub trait ModuleTrait: Send + Sync { +pub trait ModuleTrait: BaseModule + Send + Sync { fn handler(&self) -> &'static str; fn name(&self) -> String { - util::single_type_name::().to_owned() + self.single_name().to_owned() } fn description(&self) -> Option { None } + fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } + #[allow(unused_variables)] fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { } @@ -29,8 +37,10 @@ pub trait ModuleTrait: Send + Sync { fn migrations(&self) -> Vec { vec![] } +} - fn dependencies(&self) -> Vec<&'static dyn ModuleTrait> { - vec![] +impl BaseModule for M { + fn single_name(&self) -> &'static str { + util::single_type_name::() } } diff --git a/pagetop/src/api/module/mod.rs b/pagetop/src/api/module/mod.rs index b4a97393..9c186aea 100644 --- a/pagetop/src/api/module/mod.rs +++ b/pagetop/src/api/module/mod.rs @@ -1,5 +1,10 @@ mod definition; -pub use definition::ModuleTrait; +pub use definition::{ + BaseModule, + ModuleTrait, +}; pub(crate) mod all; -pub use all::register_module; +pub use all::{ + include_module, +}; diff --git a/pagetop/src/api/theme/all.rs b/pagetop/src/api/theme/all.rs index b1e47307..c4bb54fe 100644 --- a/pagetop/src/api/theme/all.rs +++ b/pagetop/src/api/theme/all.rs @@ -13,14 +13,14 @@ static THEMES: Lazy>> = Lazy::new(|| { pub fn register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); if !themes.iter().any(|t| t.handler() == theme.handler()) { - trace::debug!("Register theme: \"{}\"", theme.name()); + trace::debug!("Registering theme \"{}\"", theme.single_name()); themes.push(theme); } } -pub fn theme_by_name(name: &str) -> Option<&'static dyn ThemeTrait> { +pub fn theme_by_single_name(single_name: &str) -> Option<&'static dyn ThemeTrait> { match THEMES.write().unwrap().iter().find( - |t| t.name().to_lowercase() == name.to_lowercase() + |t| t.single_name().to_lowercase() == single_name.to_lowercase() ) { Some(theme) => Some(*theme), _ => None, diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/api/theme/definition.rs index e063b355..d5ca1db0 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/api/theme/definition.rs @@ -5,12 +5,16 @@ use crate::api::component::{Assets, ComponentTrait, Favicon}; use crate::response::page::Page; use crate::base::component::Chunck; +pub trait BaseTheme { + fn single_name(&self) -> &'static str; +} + /// Los temas deben implementar este "trait". -pub trait ThemeTrait: Send + Sync { +pub trait ThemeTrait: BaseTheme + Send + Sync { fn handler(&self) -> &'static str; fn name(&self) -> String { - util::single_type_name::().to_owned() + self.single_name().to_owned() } fn description(&self) -> Option { @@ -130,3 +134,9 @@ pub trait ThemeTrait: Send + Sync { .render() } } + +impl BaseTheme for T { + fn single_name(&self) -> &'static str { + util::single_type_name::() + } +} diff --git a/pagetop/src/api/theme/mod.rs b/pagetop/src/api/theme/mod.rs index 4456189e..ccb55a6d 100644 --- a/pagetop/src/api/theme/mod.rs +++ b/pagetop/src/api/theme/mod.rs @@ -1,8 +1,11 @@ mod definition; -pub use definition::ThemeTrait; +pub use definition::{ + BaseTheme, + ThemeTrait, +}; pub(crate) mod all; pub use all::{ register_theme, - theme_by_name, + theme_by_single_name, }; diff --git a/pagetop/src/app/application.rs b/pagetop/src/app/application.rs index 98a49f80..6432e265 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/app/application.rs @@ -40,7 +40,7 @@ impl Application { // Registra el módulo de presentación de PageTop. // Normalmente se sobrecargará en la función de inicio. - module::register_module(&base::module::demopage::Demopage); + module::include_module(&base::module::demopage::Demopage); // Registra las acciones de todos los módulos. module::all::register_actions(); From fcc022d164da07d483190b63b0d95eb5a4ff9cd7 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 8 May 2022 11:10:18 +0200 Subject: [PATCH 56/80] =?UTF-8?q?Modifica=20la=20estructura=20de=20prepara?= =?UTF-8?q?ci=C3=B3n=20de=20una=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drust/src/main.rs | 18 ++++-- pagetop-admin/src/lib.rs | 4 +- pagetop-node/src/lib.rs | 4 +- pagetop/src/api/action/definition.rs | 17 ------ pagetop/src/api/action/mod.rs | 14 ----- pagetop/src/api/component/action.rs | 48 ---------------- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/{ => core}/app/application.rs | 56 ++++++++++--------- pagetop/src/{ => core}/app/banner/mod.rs | 0 pagetop/src/{ => core}/app/banner/slant.flf | 0 pagetop/src/{ => core}/app/banner/small.flf | 0 pagetop/src/{ => core}/app/banner/speed.flf | 0 .../src/{ => core}/app/banner/starwars.flf | 0 pagetop/src/{ => core}/app/db.rs | 0 pagetop/src/core/app/definition.rs | 19 +++++++ pagetop/src/{ => core}/app/locale.rs | 0 pagetop/src/{ => core}/app/mod.rs | 3 + pagetop/src/{ => core}/app/tracing.rs | 0 pagetop/src/{api => core}/component/all.rs | 0 pagetop/src/{api => core}/component/assets.rs | 2 +- .../src/{api => core}/component/definition.rs | 10 ++-- pagetop/src/{api => core}/component/holder.rs | 0 pagetop/src/core/component/hook.rs | 48 ++++++++++++++++ pagetop/src/{api => core}/component/mod.rs | 8 +-- pagetop/src/{api/action => core/hook}/all.rs | 10 ++-- pagetop/src/core/hook/definition.rs | 17 ++++++ .../src/{api/action => core/hook}/holder.rs | 22 ++++---- pagetop/src/core/hook/mod.rs | 14 +++++ pagetop/src/{api => core}/mod.rs | 3 +- pagetop/src/{api => core}/module/all.rs | 42 +++++++++----- .../src/{api => core}/module/definition.rs | 7 ++- pagetop/src/{api => core}/module/mod.rs | 4 +- pagetop/src/{api => core}/theme/all.rs | 9 ++- pagetop/src/{api => core}/theme/definition.rs | 5 +- pagetop/src/{api => core}/theme/mod.rs | 1 + pagetop/src/lib.rs | 4 +- pagetop/src/locale.rs | 2 +- pagetop/src/prelude.rs | 11 ++-- pagetop/src/response/page/action.rs | 48 ---------------- pagetop/src/response/page/hook.rs | 48 ++++++++++++++++ pagetop/src/response/page/mod.rs | 8 +-- pagetop/src/response/page/page.rs | 15 ++--- 42 files changed, 295 insertions(+), 228 deletions(-) delete mode 100644 pagetop/src/api/action/definition.rs delete mode 100644 pagetop/src/api/action/mod.rs delete mode 100644 pagetop/src/api/component/action.rs rename pagetop/src/{ => core}/app/application.rs (57%) rename pagetop/src/{ => core}/app/banner/mod.rs (100%) rename pagetop/src/{ => core}/app/banner/slant.flf (100%) rename pagetop/src/{ => core}/app/banner/small.flf (100%) rename pagetop/src/{ => core}/app/banner/speed.flf (100%) rename pagetop/src/{ => core}/app/banner/starwars.flf (100%) rename pagetop/src/{ => core}/app/db.rs (100%) create mode 100644 pagetop/src/core/app/definition.rs rename pagetop/src/{ => core}/app/locale.rs (100%) rename pagetop/src/{ => core}/app/mod.rs (85%) rename pagetop/src/{ => core}/app/tracing.rs (100%) rename pagetop/src/{api => core}/component/all.rs (100%) rename pagetop/src/{api => core}/component/assets.rs (99%) rename pagetop/src/{api => core}/component/definition.rs (86%) rename pagetop/src/{api => core}/component/holder.rs (100%) create mode 100644 pagetop/src/core/component/hook.rs rename pagetop/src/{api => core}/component/mod.rs (82%) rename pagetop/src/{api/action => core/hook}/all.rs (58%) create mode 100644 pagetop/src/core/hook/definition.rs rename pagetop/src/{api/action => core/hook}/holder.rs (50%) create mode 100644 pagetop/src/core/hook/mod.rs rename pagetop/src/{api => core}/mod.rs (57%) rename pagetop/src/{api => core}/module/all.rs (54%) rename pagetop/src/{api => core}/module/definition.rs (89%) rename pagetop/src/{api => core}/module/mod.rs (65%) rename pagetop/src/{api => core}/theme/all.rs (83%) rename pagetop/src/{api => core}/theme/definition.rs (96%) rename pagetop/src/{api => core}/theme/mod.rs (88%) delete mode 100644 pagetop/src/response/page/action.rs create mode 100644 pagetop/src/response/page/hook.rs diff --git a/drust/src/main.rs b/drust/src/main.rs index 6b610c8b..66a8d192 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,12 +1,18 @@ -use pagetop::prelude::*; +use pagetop::{prelude::*, core::app::AppTrait}; -fn bootstrap() { - include_module(&pagetop_admin::Admin); - include_module(&pagetop_user::User); - include_module(&pagetop_node::Node); +struct Drust; + +impl AppTrait for Drust { + fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { + vec![ + &pagetop_admin::Admin, + &pagetop_user::User, + &pagetop_node::Node, + ] + } } #[actix_web::main] async fn main() -> std::io::Result<()> { - Application::prepare(UsingBootstrap::Fn(bootstrap)).await?.run()?.await + Application::prepare(Drust).await?.run()?.await } diff --git a/pagetop-admin/src/lib.rs b/pagetop-admin/src/lib.rs index d05138b4..d495ecaf 100644 --- a/pagetop-admin/src/lib.rs +++ b/pagetop-admin/src/lib.rs @@ -28,9 +28,9 @@ impl ModuleTrait for Admin { ); } - fn actions(&self) -> Vec { + fn actions(&self) -> Vec { vec![ - action_item!(ActionBeforeRenderPage => before_render_page) + hook_item!(BeforeRenderPageHook => before_render_page) ] } } diff --git a/pagetop-node/src/lib.rs b/pagetop-node/src/lib.rs index 98af01bd..5556fefe 100644 --- a/pagetop-node/src/lib.rs +++ b/pagetop-node/src/lib.rs @@ -26,9 +26,9 @@ impl ModuleTrait for Node { cfg.route("/node", app::web::get().to(node)); } - fn actions(&self) -> Vec { + fn actions(&self) -> Vec { vec![ - action_item!(ActionBeforeRenderPage => before_render_page, -1) + hook_item!(BeforeRenderPageHook => before_render_page, -1) ] } diff --git a/pagetop/src/api/action/definition.rs b/pagetop/src/api/action/definition.rs deleted file mode 100644 index 1c950686..00000000 --- a/pagetop/src/api/action/definition.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub use std::any::Any as AnyAction; - -pub trait ActionTrait: AnyAction + Send + Sync { - fn new() -> Self where Self: Sized; - - fn handler(&self) -> &'static str; - - fn weight(&self) -> isize { - 0 - } - - fn as_ref_any(&self) -> &dyn AnyAction; -} - -pub fn action_ref(action: &dyn ActionTrait) -> &A { - action.as_ref_any().downcast_ref::().unwrap() -} diff --git a/pagetop/src/api/action/mod.rs b/pagetop/src/api/action/mod.rs deleted file mode 100644 index 53e32f8d..00000000 --- a/pagetop/src/api/action/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -mod definition; -pub use definition::{ - ActionTrait, - AnyAction, - action_ref, -}; - -mod holder; -pub use holder::ActionItem; -use holder::ActionsHolder; - -mod all; -pub use all::run_actions; -pub(crate) use all::add_action; diff --git a/pagetop/src/api/component/action.rs b/pagetop/src/api/component/action.rs deleted file mode 100644 index 243646cc..00000000 --- a/pagetop/src/api/component/action.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::api::action::{ActionTrait, AnyAction}; -use super::{Assets, ComponentTrait}; - -pub const BEFORE_RENDER_COMPONENT_ACTION: &str = "pagetop::action::before_render_component"; - -pub struct BeforeRenderComponentAction { - action: Option, - weight: isize, -} - -impl ActionTrait for BeforeRenderComponentAction { - fn new() -> Self { - BeforeRenderComponentAction { - action: None, - weight: 0, - } - } - - fn handler(&self) -> &'static str { - BEFORE_RENDER_COMPONENT_ACTION - } - - fn weight(&self) -> isize { - self.weight - } - - fn as_ref_any(&self) -> &dyn AnyAction { - self - } -} - -impl BeforeRenderComponentAction { - pub fn with_action(mut self, action: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { - self.action = Some(action); - self - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) { - if let Some(action) = self.action { - action(component, assets) - } - } -} diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index dcf209b0..189eb0c4 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -95,7 +95,7 @@ impl Form { self } - pub fn with_action(mut self, action: &str) -> Self { + pub fn with_hook(mut self, action: &str) -> Self { self.alter_action(action); self } diff --git a/pagetop/src/app/application.rs b/pagetop/src/core/app/application.rs similarity index 57% rename from pagetop/src/app/application.rs rename to pagetop/src/core/app/application.rs index 6432e265..01af2c5b 100644 --- a/pagetop/src/app/application.rs +++ b/pagetop/src/core/app/application.rs @@ -1,57 +1,63 @@ -use crate::{Lazy, app, base, trace}; +use crate::{Lazy, base, trace}; use crate::config::SETTINGS; -use crate::api::{module, theme}; +use crate::core::{module, theme}; +use super::AppTrait; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; pub struct Application { - server: app::Server, + server: super::Server, } -pub enum UsingBootstrap {Fn(fn()), No} - impl Application { - pub async fn prepare(bootstrap: UsingBootstrap) -> Result { + pub async fn prepare(brrrz: impl AppTrait) -> Result { // Rótulo de presentación. - app::banner::print_on_startup(); + super::banner::print_on_startup(); // Inicia registro de trazas y eventos. - Lazy::force(&app::tracing::TRACING); + Lazy::force(&super::tracing::TRACING); // Valida el identificador de idioma. - Lazy::force(&app::locale::LANGID); + Lazy::force(&super::locale::LANGID); // Conecta con la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] - Lazy::force(&app::db::DBCONN); + Lazy::force(&super::db::DBCONN); // Registra los temas predeterminados. - theme::register_theme(&base::theme::aliner::Aliner); - theme::register_theme(&base::theme::minimal::Minimal); - theme::register_theme(&base::theme::bootsier::Bootsier); - theme::register_theme(&base::theme::bulmix::Bulmix); + theme::register_themes(vec![ + &base::theme::aliner::Aliner, + &base::theme::minimal::Minimal, + &base::theme::bootsier::Bootsier, + &base::theme::bulmix::Bulmix, + ]); + theme::register_themes(brrrz.register_themes()); + + // Habilita los módulos predeterminados. + module::enable_modules(brrrz.enabled_modules()); + // Habilita el módulo de presentación de PageTop. + // Normalmente se sobrecargará en la función de inicio. + module::enable_module(&base::module::demopage::Demopage); + + // Registra las acciones de todos los módulos. + module::all::register_hooks(); // Ejecuta la función de inicio de la aplicación. trace::info!("Calling application bootstrap"); + brrrz.bootstrap(); + /* if let UsingBootstrap::Fn(bootstrap) = bootstrap { let _ = &bootstrap(); - } - - // Registra el módulo de presentación de PageTop. - // Normalmente se sobrecargará en la función de inicio. - module::include_module(&base::module::demopage::Demopage); - - // Registra las acciones de todos los módulos. - module::all::register_actions(); + }*/ // Actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] module::all::run_migrations(); // Prepara el servidor web. - let server = app::HttpServer::new(move || { - app::App::new() + let server = super::HttpServer::new(move || { + super::App::new() .wrap(tracing_actix_web::TracingLogger) .wrap(NormalizePath::new(TrailingSlash::Trim)) .configure(&module::all::modules) @@ -66,7 +72,7 @@ impl Application { Ok(Self { server }) } - pub fn run(self) -> Result { + pub fn run(self) -> Result { Ok(self.server) } } diff --git a/pagetop/src/app/banner/mod.rs b/pagetop/src/core/app/banner/mod.rs similarity index 100% rename from pagetop/src/app/banner/mod.rs rename to pagetop/src/core/app/banner/mod.rs diff --git a/pagetop/src/app/banner/slant.flf b/pagetop/src/core/app/banner/slant.flf similarity index 100% rename from pagetop/src/app/banner/slant.flf rename to pagetop/src/core/app/banner/slant.flf diff --git a/pagetop/src/app/banner/small.flf b/pagetop/src/core/app/banner/small.flf similarity index 100% rename from pagetop/src/app/banner/small.flf rename to pagetop/src/core/app/banner/small.flf diff --git a/pagetop/src/app/banner/speed.flf b/pagetop/src/core/app/banner/speed.flf similarity index 100% rename from pagetop/src/app/banner/speed.flf rename to pagetop/src/core/app/banner/speed.flf diff --git a/pagetop/src/app/banner/starwars.flf b/pagetop/src/core/app/banner/starwars.flf similarity index 100% rename from pagetop/src/app/banner/starwars.flf rename to pagetop/src/core/app/banner/starwars.flf diff --git a/pagetop/src/app/db.rs b/pagetop/src/core/app/db.rs similarity index 100% rename from pagetop/src/app/db.rs rename to pagetop/src/core/app/db.rs diff --git a/pagetop/src/core/app/definition.rs b/pagetop/src/core/app/definition.rs new file mode 100644 index 00000000..7c13f9b0 --- /dev/null +++ b/pagetop/src/core/app/definition.rs @@ -0,0 +1,19 @@ +use crate::core::module::ModuleTrait; +use crate::core::theme::ThemeTrait; + +pub trait AppTrait: Send + Sync { + fn bootstrap(&self) { + } + + fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } + + fn disabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { + vec![] + } + + fn register_themes(&self) -> Vec<&'static dyn ThemeTrait> { + vec![] + } +} diff --git a/pagetop/src/app/locale.rs b/pagetop/src/core/app/locale.rs similarity index 100% rename from pagetop/src/app/locale.rs rename to pagetop/src/core/app/locale.rs diff --git a/pagetop/src/app/mod.rs b/pagetop/src/core/app/mod.rs similarity index 85% rename from pagetop/src/app/mod.rs rename to pagetop/src/core/app/mod.rs index 07404f64..04feaf83 100644 --- a/pagetop/src/app/mod.rs +++ b/pagetop/src/core/app/mod.rs @@ -12,4 +12,7 @@ pub mod locale; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; +mod definition; +pub use definition::AppTrait; + pub mod application; diff --git a/pagetop/src/app/tracing.rs b/pagetop/src/core/app/tracing.rs similarity index 100% rename from pagetop/src/app/tracing.rs rename to pagetop/src/core/app/tracing.rs diff --git a/pagetop/src/api/component/all.rs b/pagetop/src/core/component/all.rs similarity index 100% rename from pagetop/src/api/component/all.rs rename to pagetop/src/core/component/all.rs diff --git a/pagetop/src/api/component/assets.rs b/pagetop/src/core/component/assets.rs similarity index 99% rename from pagetop/src/api/component/assets.rs rename to pagetop/src/core/component/assets.rs index 1ff78d23..1274348d 100644 --- a/pagetop/src/api/component/assets.rs +++ b/pagetop/src/core/component/assets.rs @@ -1,7 +1,7 @@ use crate::{Lazy, base, concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, PreEscaped, html}; -use crate::api::theme::*; +use crate::core::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { match theme_by_single_name(&SETTINGS.app.theme) { diff --git a/pagetop/src/api/component/definition.rs b/pagetop/src/core/component/definition.rs similarity index 86% rename from pagetop/src/api/component/definition.rs rename to pagetop/src/core/component/definition.rs index 4381b08e..45fa3e91 100644 --- a/pagetop/src/api/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -1,7 +1,7 @@ use crate::util; use crate::html::{Markup, html}; -use crate::api::action::{action_ref, run_actions}; -use super::{BEFORE_RENDER_COMPONENT_ACTION, BeforeRenderComponentAction}; +use crate::core::hook::{hook_ref, run_hooks}; +use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook}; use super::Assets; pub use std::any::Any as AnyComponent; @@ -54,9 +54,9 @@ pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) component.before_render(assets); // Acciones de los módulos antes de renderizar el componente. - run_actions( - BEFORE_RENDER_COMPONENT_ACTION, - |a| action_ref::(&**a).run(component, assets) + run_hooks( + BEFORE_RENDER_COMPONENT_HOOK, + |a| hook_ref::(&**a).run(component, assets) ); // Acciones del tema antes de renderizar el componente. diff --git a/pagetop/src/api/component/holder.rs b/pagetop/src/core/component/holder.rs similarity index 100% rename from pagetop/src/api/component/holder.rs rename to pagetop/src/core/component/holder.rs diff --git a/pagetop/src/core/component/hook.rs b/pagetop/src/core/component/hook.rs new file mode 100644 index 00000000..a35e09ad --- /dev/null +++ b/pagetop/src/core/component/hook.rs @@ -0,0 +1,48 @@ +use crate::core::hook::{HookTrait, AnyHook}; +use super::{Assets, ComponentTrait}; + +pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::action::before_render_component"; + +pub struct BeforeRenderComponentHook { + hook: Option, + weight: isize, +} + +impl HookTrait for BeforeRenderComponentHook { + fn new() -> Self { + BeforeRenderComponentHook { + hook: None, + weight: 0, + } + } + + fn handler(&self) -> &'static str { + BEFORE_RENDER_COMPONENT_HOOK + } + + fn weight(&self) -> isize { + self.weight + } + + fn as_ref_any(&self) -> &dyn AnyHook { + self + } +} + +impl BeforeRenderComponentHook { + pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { + self.hook = Some(hook); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) { + if let Some(hook) = self.hook { + hook(component, assets) + } + } +} diff --git a/pagetop/src/api/component/mod.rs b/pagetop/src/core/component/mod.rs similarity index 82% rename from pagetop/src/api/component/mod.rs rename to pagetop/src/core/component/mod.rs index a8ee3c4d..1f710deb 100644 --- a/pagetop/src/api/component/mod.rs +++ b/pagetop/src/core/component/mod.rs @@ -1,7 +1,7 @@ -mod action; -pub use action::{ - BEFORE_RENDER_COMPONENT_ACTION, - BeforeRenderComponentAction, +mod hook; +pub use hook::{ + BEFORE_RENDER_COMPONENT_HOOK, + BeforeRenderComponentHook, }; mod assets; diff --git a/pagetop/src/api/action/all.rs b/pagetop/src/core/hook/all.rs similarity index 58% rename from pagetop/src/api/action/all.rs rename to pagetop/src/core/hook/all.rs index cb9bfb8d..2329b251 100644 --- a/pagetop/src/api/action/all.rs +++ b/pagetop/src/core/hook/all.rs @@ -1,25 +1,25 @@ use crate::Lazy; -use super::{ActionItem, ActionsHolder}; +use super::{HookItem, HooksHolder}; use std::sync::RwLock; use std::collections::HashMap; // Registered actions. -static ACTIONS: Lazy>> = Lazy::new(|| { +static ACTIONS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); -pub fn add_action(action: ActionItem) { +pub fn add_hook(action: HookItem) { let mut hmap = ACTIONS.write().unwrap(); let action_handler = action.handler(); if let Some(actions) = hmap.get_mut(action_handler) { actions.add(action); } else { - hmap.insert(action_handler, ActionsHolder::new_with(action)); + hmap.insert(action_handler, HooksHolder::new_with(action)); } } -pub fn run_actions(action_handler: &str, f: F) where F: FnMut(&ActionItem) -> B { +pub fn run_hooks(action_handler: &str, f: F) where F: FnMut(&HookItem) -> B { if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) { actions.iter_map(f) } diff --git a/pagetop/src/core/hook/definition.rs b/pagetop/src/core/hook/definition.rs new file mode 100644 index 00000000..823e830e --- /dev/null +++ b/pagetop/src/core/hook/definition.rs @@ -0,0 +1,17 @@ +pub use std::any::Any as AnyHook; + +pub trait HookTrait: AnyHook + Send + Sync { + fn new() -> Self where Self: Sized; + + fn handler(&self) -> &'static str; + + fn weight(&self) -> isize { + 0 + } + + fn as_ref_any(&self) -> &dyn AnyHook; +} + +pub fn hook_ref(action: &dyn HookTrait) -> &A { + action.as_ref_any().downcast_ref::().unwrap() +} diff --git a/pagetop/src/api/action/holder.rs b/pagetop/src/core/hook/holder.rs similarity index 50% rename from pagetop/src/api/action/holder.rs rename to pagetop/src/core/hook/holder.rs index 7009e103..3cd6d369 100644 --- a/pagetop/src/api/action/holder.rs +++ b/pagetop/src/core/hook/holder.rs @@ -1,36 +1,36 @@ -use super::ActionTrait; +use super::HookTrait; use std::sync::{Arc, RwLock}; -pub type ActionItem = Box; +pub type HookItem = Box; #[macro_export] -macro_rules! action_item { +macro_rules! hook_item { ( $action:ident => $f:ident $(, $weight:expr)? ) => {{ - Box::new($action::new().with_action($f)$(.with_weight($weight))?) + Box::new($action::new().with_hook($f)$(.with_weight($weight))?) }}; } -pub struct ActionsHolder(Arc>>); +pub struct HooksHolder(Arc>>); -impl ActionsHolder { +impl HooksHolder { pub fn new() -> Self { - ActionsHolder(Arc::new(RwLock::new(Vec::new()))) + HooksHolder(Arc::new(RwLock::new(Vec::new()))) } - pub fn new_with(action: ActionItem) -> Self { - let mut container = ActionsHolder::new(); + pub fn new_with(action: HookItem) -> Self { + let mut container = HooksHolder::new(); container.add(action); container } - pub fn add(&mut self, action: ActionItem) { + pub fn add(&mut self, action: HookItem) { let mut actions = self.0.write().unwrap(); actions.push(action); actions.sort_by_key(|a| a.weight()); } - pub fn iter_map(&self, f: F) where Self: Sized, F: FnMut(&ActionItem) -> B { + pub fn iter_map(&self, f: F) where Self: Sized, F: FnMut(&HookItem) -> B { let _: Vec<_> = self.0.read().unwrap().iter().map(f).collect(); } } diff --git a/pagetop/src/core/hook/mod.rs b/pagetop/src/core/hook/mod.rs new file mode 100644 index 00000000..8b83a58d --- /dev/null +++ b/pagetop/src/core/hook/mod.rs @@ -0,0 +1,14 @@ +mod definition; +pub use definition::{ + HookTrait, + AnyHook, + hook_ref, +}; + +mod holder; +pub use holder::HookItem; +use holder::HooksHolder; + +mod all; +pub use all::run_hooks; +pub(crate) use all::add_hook; diff --git a/pagetop/src/api/mod.rs b/pagetop/src/core/mod.rs similarity index 57% rename from pagetop/src/api/mod.rs rename to pagetop/src/core/mod.rs index ff5daff9..e3208027 100644 --- a/pagetop/src/api/mod.rs +++ b/pagetop/src/core/mod.rs @@ -1,4 +1,5 @@ -pub mod action; // API to define functions that alter the behavior of PageTop core. +pub mod app; // API to initialize the PageTop base application. pub mod component; // API to build new components. +pub mod hook; // API to define functions that alter the behavior of PageTop core. pub mod module; // API to add new features with modules. pub mod theme; // API to create themes. diff --git a/pagetop/src/api/module/all.rs b/pagetop/src/core/module/all.rs similarity index 54% rename from pagetop/src/api/module/all.rs rename to pagetop/src/core/module/all.rs index 778dba2e..ac5e8144 100644 --- a/pagetop/src/api/module/all.rs +++ b/pagetop/src/core/module/all.rs @@ -1,26 +1,38 @@ -use crate::{Lazy, app, run_now, trace}; -use crate::api::action::add_action; +use crate::{Lazy, run_now, trace}; +use crate::core::app; +use crate::core::hook::add_hook; use crate::db::*; use super::ModuleTrait; use std::sync::RwLock; -// Módulos registrados. -static MODULES: Lazy>> = Lazy::new(|| { +// Enabled modules. +static ENABLED_MODULES: Lazy>> = Lazy::new(|| { RwLock::new(Vec::new()) }); -pub fn include_module(module: &'static dyn ModuleTrait) { +/* Disabled modules. +static DISABLED_MODULES: Lazy>> = Lazy::new(|| { + RwLock::new(Vec::new()) +}); */ + +pub fn enable_modules(modules: Vec<&'static dyn ModuleTrait>) { + for m in modules { + enable_module(m) + } +} + +pub fn enable_module(module: &'static dyn ModuleTrait) { let mut list: Vec<&dyn ModuleTrait> = Vec::new(); add_to(&mut list, module); list.reverse(); - MODULES.write().unwrap().append(&mut list); + ENABLED_MODULES.write().unwrap().append(&mut list); } fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { - if !MODULES.read().unwrap().iter().any(|m| m.handler() == module.handler()) { + if !ENABLED_MODULES.read().unwrap().iter().any(|m| m.handler() == module.handler()) { if !list.iter().any(|m| m.handler() == module.handler()) { - trace::debug!("Including module \"{}\"", module.single_name()); + trace::debug!("Enabling module \"{}\"", module.single_name()); list.push(module); let mut dependencies = module.dependencies(); @@ -32,16 +44,20 @@ fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { } } +#[allow(unused_variables)] +pub fn disable_module(module: &'static dyn ModuleTrait) { +} + pub fn modules(cfg: &mut app::web::ServiceConfig) { - for m in MODULES.read().unwrap().iter() { + for m in ENABLED_MODULES.read().unwrap().iter() { m.configure_service(cfg); } } -pub fn register_actions() { - for m in MODULES.read().unwrap().iter() { +pub fn register_hooks() { + for m in ENABLED_MODULES.read().unwrap().iter() { for a in m.actions().into_iter() { - add_action(a); + add_hook(a); } } } @@ -53,7 +69,7 @@ pub fn run_migrations() { impl MigratorTrait for Migrator { fn migrations() -> Vec { let mut migrations = vec![]; - for m in MODULES.read().unwrap().iter() { + for m in ENABLED_MODULES.read().unwrap().iter() { migrations.append(&mut m.migrations()); } migrations diff --git a/pagetop/src/api/module/definition.rs b/pagetop/src/core/module/definition.rs similarity index 89% rename from pagetop/src/api/module/definition.rs rename to pagetop/src/core/module/definition.rs index e457e3f0..89904cc0 100644 --- a/pagetop/src/api/module/definition.rs +++ b/pagetop/src/core/module/definition.rs @@ -1,5 +1,6 @@ -use crate::{app, util}; -use crate::api::action::ActionItem; +use crate::util; +use crate::core::app; +use crate::core::hook::HookItem; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] use crate::db::MigrationItem; @@ -28,7 +29,7 @@ pub trait ModuleTrait: BaseModule + Send + Sync { fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { } - fn actions(&self) -> Vec { + fn actions(&self) -> Vec { vec![] } diff --git a/pagetop/src/api/module/mod.rs b/pagetop/src/core/module/mod.rs similarity index 65% rename from pagetop/src/api/module/mod.rs rename to pagetop/src/core/module/mod.rs index 9c186aea..424595e3 100644 --- a/pagetop/src/api/module/mod.rs +++ b/pagetop/src/core/module/mod.rs @@ -6,5 +6,7 @@ pub use definition::{ pub(crate) mod all; pub use all::{ - include_module, + disable_module, + enable_module, + enable_modules, }; diff --git a/pagetop/src/api/theme/all.rs b/pagetop/src/core/theme/all.rs similarity index 83% rename from pagetop/src/api/theme/all.rs rename to pagetop/src/core/theme/all.rs index c4bb54fe..2a54f578 100644 --- a/pagetop/src/api/theme/all.rs +++ b/pagetop/src/core/theme/all.rs @@ -1,4 +1,5 @@ -use crate::{Lazy, app, theme_static_files, trace}; +use crate::{Lazy, theme_static_files, trace}; +use crate::core::app; use super::ThemeTrait; use std::sync::RwLock; @@ -10,6 +11,12 @@ static THEMES: Lazy>> = Lazy::new(|| { RwLock::new(Vec::new()) }); +pub fn register_themes(themes: Vec<&'static dyn ThemeTrait>) { + for t in themes { + register_theme(t) + } +} + pub fn register_theme(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); if !themes.iter().any(|t| t.handler() == theme.handler()) { diff --git a/pagetop/src/api/theme/definition.rs b/pagetop/src/core/theme/definition.rs similarity index 96% rename from pagetop/src/api/theme/definition.rs rename to pagetop/src/core/theme/definition.rs index d5ca1db0..697f52ea 100644 --- a/pagetop/src/api/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -1,7 +1,8 @@ -use crate::{app, concat_string, util}; +use crate::{concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::api::component::{Assets, ComponentTrait, Favicon}; +use crate::core::app; +use crate::core::component::{Assets, ComponentTrait, Favicon}; use crate::response::page::Page; use crate::base::component::Chunck; diff --git a/pagetop/src/api/theme/mod.rs b/pagetop/src/core/theme/mod.rs similarity index 88% rename from pagetop/src/api/theme/mod.rs rename to pagetop/src/core/theme/mod.rs index ccb55a6d..5a4b4060 100644 --- a/pagetop/src/api/theme/mod.rs +++ b/pagetop/src/core/theme/mod.rs @@ -7,5 +7,6 @@ pub use definition::{ pub(crate) mod all; pub use all::{ register_theme, + register_themes, theme_by_single_name, }; diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 20a25229..64da0481 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -18,10 +18,10 @@ pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a base de datos. -pub mod api; // Main APIs for actions, components, modules and themes. +pub mod core; // Main APIs for actions, components, modules and themes. pub mod response; // Tipos de respuestas web. -pub mod app; // Aplicación y servidor web. +//pub mod app; // Aplicación y servidor web. pub mod base; // Base de componentes, módulos y temas. pub mod util; // Macros y funciones útiles. diff --git a/pagetop/src/locale.rs b/pagetop/src/locale.rs index 93e9e7e8..98e88823 100644 --- a/pagetop/src/locale.rs +++ b/pagetop/src/locale.rs @@ -7,7 +7,7 @@ pub use fluent_templates::fluent_bundle::FluentValue; macro_rules! localize { ( $dir_locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; - use $crate::app::locale::LANGID; + use $crate::core::app::locale::LANGID; static_locale! { static LOCALES = { diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 357c31cf..0495bc70 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -20,17 +20,20 @@ pub use crate::{ migration_item, }; -pub use crate::{action_item, api::{ - action::*, +pub use crate::{hook_item, core::{ +// app::*, component::*, + hook::*, module::*, theme::*, }}; +pub use crate::core::app; +pub use crate::core::app::application::Application; pub use crate::response::page::*; -pub use crate::app; -pub use crate::app::application::{Application, UsingBootstrap}; +//pub use crate::app; +//pub use crate::app::application::{Application, UsingBootstrap}; pub use crate::base::component::*; diff --git a/pagetop/src/response/page/action.rs b/pagetop/src/response/page/action.rs deleted file mode 100644 index 7869987c..00000000 --- a/pagetop/src/response/page/action.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::api::action::{ActionTrait, AnyAction}; -use super::Page; - -pub const BEFORE_RENDER_PAGE_ACTION: &str = "pagetop::action::before_render_page"; - -pub struct ActionBeforeRenderPage { - action: Option, - weight: isize, -} - -impl ActionTrait for ActionBeforeRenderPage { - fn new() -> Self { - ActionBeforeRenderPage { - action: None, - weight: 0, - } - } - - fn handler(&self) -> &'static str { - BEFORE_RENDER_PAGE_ACTION - } - - fn weight(&self) -> isize { - self.weight - } - - fn as_ref_any(&self) -> &dyn AnyAction { - self - } -} - -impl ActionBeforeRenderPage { - pub fn with_action(mut self, action: fn(&mut Page)) -> Self { - self.action = Some(action); - self - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn run(&self, page: &mut Page) { - if let Some(action) = self.action { - action(page) - } - } -} diff --git a/pagetop/src/response/page/hook.rs b/pagetop/src/response/page/hook.rs new file mode 100644 index 00000000..e63a189c --- /dev/null +++ b/pagetop/src/response/page/hook.rs @@ -0,0 +1,48 @@ +use crate::core::hook::{HookTrait, AnyHook}; +use super::Page; + +pub const BEFORE_RENDER_PAGE_HOOK: &str = "pagetop::action::before_render_page"; + +pub struct BeforeRenderPageHook { + hook: Option, + weight: isize, +} + +impl HookTrait for BeforeRenderPageHook { + fn new() -> Self { + BeforeRenderPageHook { + hook: None, + weight: 0, + } + } + + fn handler(&self) -> &'static str { + BEFORE_RENDER_PAGE_HOOK + } + + fn weight(&self) -> isize { + self.weight + } + + fn as_ref_any(&self) -> &dyn AnyHook { + self + } +} + +impl BeforeRenderPageHook { + pub fn with_hook(mut self, hook: fn(&mut Page)) -> Self { + self.hook = Some(hook); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn run(&self, page: &mut Page) { + if let Some(hook) = self.hook { + hook(page) + } + } +} diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page/mod.rs index e08e55f0..82c5d7da 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page/mod.rs @@ -1,7 +1,7 @@ -mod action; -pub use action::{ - BEFORE_RENDER_PAGE_ACTION, - ActionBeforeRenderPage, +mod hook; +pub use hook::{ + BEFORE_RENDER_PAGE_HOOK, + BeforeRenderPageHook, }; mod page; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/page.rs index a4fc741b..6febf1ac 100644 --- a/pagetop/src/response/page/page.rs +++ b/pagetop/src/response/page/page.rs @@ -1,9 +1,10 @@ -use crate::{Lazy, app, trace}; +use crate::{Lazy, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::api::action::{action_ref, run_actions}; -use crate::api::component::*; -use super::{BEFORE_RENDER_PAGE_ACTION, ActionBeforeRenderPage}; +use crate::core::app; +use crate::core::hook::{hook_ref, run_hooks}; +use crate::core::component::*; +use super::{BEFORE_RENDER_PAGE_HOOK, BeforeRenderPageHook}; use std::collections::HashMap; @@ -151,9 +152,9 @@ impl<'a> Page<'a> { pub fn render(&mut self) -> app::Result { // Acciones de los módulos antes de renderizar la página. - run_actions( - BEFORE_RENDER_PAGE_ACTION, - |a| action_ref::(&**a).run(self) + run_hooks( + BEFORE_RENDER_PAGE_HOOK, + |a| hook_ref::(&**a).run(self) ); // Acciones del tema antes de renderizar la página. From 897ce6bb64ade574f9878059e28b670b286d77f8 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 8 May 2022 11:23:11 +0200 Subject: [PATCH 57/80] =?UTF-8?q?Corrige=20errores=20de=20asignaci=C3=B3n?= =?UTF-8?q?=20de=20identificadores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/form/form.rs | 2 +- pagetop/src/base/theme/aliner/mod.rs | 2 +- pagetop/src/base/theme/bootsier/mod.rs | 2 +- pagetop/src/base/theme/bulmix/mod.rs | 2 +- pagetop/src/core/component/hook.rs | 2 +- pagetop/src/core/component/mod.rs | 6 ++---- pagetop/src/core/hook/all.rs | 8 ++++---- pagetop/src/core/hook/definition.rs | 4 ++-- pagetop/src/core/hook/holder.rs | 12 ++++++------ pagetop/src/core/theme/all.rs | 2 +- pagetop/src/core/theme/definition.rs | 2 +- pagetop/src/response/page/hook.rs | 2 +- 12 files changed, 22 insertions(+), 24 deletions(-) diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 189eb0c4..dcf209b0 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -95,7 +95,7 @@ impl Form { self } - pub fn with_hook(mut self, action: &str) -> Self { + pub fn with_action(mut self, action: &str) -> Self { self.alter_action(action); self } diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner/mod.rs index f3c90f9b..d27c4632 100644 --- a/pagetop/src/base/theme/aliner/mod.rs +++ b/pagetop/src/base/theme/aliner/mod.rs @@ -11,7 +11,7 @@ impl ThemeTrait for Aliner { ALINER_THEME } - fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/aliner"); } diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier/mod.rs index a8be7118..5471b5cf 100644 --- a/pagetop/src/base/theme/bootsier/mod.rs +++ b/pagetop/src/base/theme/bootsier/mod.rs @@ -13,7 +13,7 @@ impl ThemeTrait for Bootsier { BOOTSIER_THEME } - fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bootsier"); } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 477dbbf7..e047b214 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -11,7 +11,7 @@ impl ThemeTrait for Bulmix { BULMIX_THEME } - fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/bulmix"); } diff --git a/pagetop/src/core/component/hook.rs b/pagetop/src/core/component/hook.rs index a35e09ad..f52d755b 100644 --- a/pagetop/src/core/component/hook.rs +++ b/pagetop/src/core/component/hook.rs @@ -1,7 +1,7 @@ use crate::core::hook::{HookTrait, AnyHook}; use super::{Assets, ComponentTrait}; -pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::action::before_render_component"; +pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::hook::before_render_component"; pub struct BeforeRenderComponentHook { hook: Option, diff --git a/pagetop/src/core/component/mod.rs b/pagetop/src/core/component/mod.rs index 1f710deb..c0c78a57 100644 --- a/pagetop/src/core/component/mod.rs +++ b/pagetop/src/core/component/mod.rs @@ -25,10 +25,8 @@ mod holder; pub use holder::ComponentsHolder; mod all; -pub use all::{ - add_component_to, - common_components, -}; +pub use all::add_component_to; +pub(crate) use all::common_components; pub fn render_always() -> bool { true } diff --git a/pagetop/src/core/hook/all.rs b/pagetop/src/core/hook/all.rs index 2329b251..5c6f28d9 100644 --- a/pagetop/src/core/hook/all.rs +++ b/pagetop/src/core/hook/all.rs @@ -9,13 +9,13 @@ static ACTIONS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); -pub fn add_hook(action: HookItem) { +pub fn add_hook(hook: HookItem) { let mut hmap = ACTIONS.write().unwrap(); - let action_handler = action.handler(); + let action_handler = hook.handler(); if let Some(actions) = hmap.get_mut(action_handler) { - actions.add(action); + actions.add(hook); } else { - hmap.insert(action_handler, HooksHolder::new_with(action)); + hmap.insert(action_handler, HooksHolder::new_with(hook)); } } diff --git a/pagetop/src/core/hook/definition.rs b/pagetop/src/core/hook/definition.rs index 823e830e..e21ea10f 100644 --- a/pagetop/src/core/hook/definition.rs +++ b/pagetop/src/core/hook/definition.rs @@ -12,6 +12,6 @@ pub trait HookTrait: AnyHook + Send + Sync { fn as_ref_any(&self) -> &dyn AnyHook; } -pub fn hook_ref(action: &dyn HookTrait) -> &A { - action.as_ref_any().downcast_ref::().unwrap() +pub fn hook_ref(hook: &dyn HookTrait) -> &A { + hook.as_ref_any().downcast_ref::().unwrap() } diff --git a/pagetop/src/core/hook/holder.rs b/pagetop/src/core/hook/holder.rs index 3cd6d369..cd138c67 100644 --- a/pagetop/src/core/hook/holder.rs +++ b/pagetop/src/core/hook/holder.rs @@ -6,8 +6,8 @@ pub type HookItem = Box; #[macro_export] macro_rules! hook_item { - ( $action:ident => $f:ident $(, $weight:expr)? ) => {{ - Box::new($action::new().with_hook($f)$(.with_weight($weight))?) + ( $hook:ident => $f:ident $(, $weight:expr)? ) => {{ + Box::new($hook::new().with_hook($f)$(.with_weight($weight))?) }}; } @@ -18,15 +18,15 @@ impl HooksHolder { HooksHolder(Arc::new(RwLock::new(Vec::new()))) } - pub fn new_with(action: HookItem) -> Self { + pub fn new_with(hook: HookItem) -> Self { let mut container = HooksHolder::new(); - container.add(action); + container.add(hook); container } - pub fn add(&mut self, action: HookItem) { + pub fn add(&mut self, hook: HookItem) { let mut actions = self.0.write().unwrap(); - actions.push(action); + actions.push(hook); actions.sort_by_key(|a| a.weight()); } diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/core/theme/all.rs index 2a54f578..ba725b71 100644 --- a/pagetop/src/core/theme/all.rs +++ b/pagetop/src/core/theme/all.rs @@ -38,6 +38,6 @@ pub fn themes(cfg: &mut app::web::ServiceConfig) { theme_static_files!(cfg, "/theme"); for t in THEMES.read().unwrap().iter() { - t.configure_theme(cfg); + t.configure_service(cfg); } } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 697f52ea..74457e19 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -23,7 +23,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { } #[allow(unused_variables)] - fn configure_theme(&self, cfg: &mut app::web::ServiceConfig) { + fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { } #[allow(unused_variables)] diff --git a/pagetop/src/response/page/hook.rs b/pagetop/src/response/page/hook.rs index e63a189c..d482fb56 100644 --- a/pagetop/src/response/page/hook.rs +++ b/pagetop/src/response/page/hook.rs @@ -1,7 +1,7 @@ use crate::core::hook::{HookTrait, AnyHook}; use super::Page; -pub const BEFORE_RENDER_PAGE_HOOK: &str = "pagetop::action::before_render_page"; +pub const BEFORE_RENDER_PAGE_HOOK: &str = "pagetop::hook::before_render_page"; pub struct BeforeRenderPageHook { hook: Option, From 6b38e4b8ae2f667353566408cfab9f2da520c55a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 8 May 2022 12:53:16 +0200 Subject: [PATCH 58/80] Modifica y depura el uso de la api interna --- drust/src/main.rs | 5 ++-- pagetop/src/core/app/application.rs | 35 ++++++++++++---------------- pagetop/src/core/app/definition.rs | 15 +++++++----- pagetop/src/core/app/mod.rs | 1 - pagetop/src/core/component/assets.rs | 4 ++-- pagetop/src/core/module/all.rs | 8 +++---- pagetop/src/core/module/mod.rs | 5 ---- pagetop/src/core/theme/all.rs | 4 ++-- pagetop/src/core/theme/mod.rs | 5 ---- pagetop/src/lib.rs | 3 +-- pagetop/src/prelude.rs | 8 +++---- 11 files changed, 39 insertions(+), 54 deletions(-) diff --git a/drust/src/main.rs b/drust/src/main.rs index 66a8d192..6b1f4543 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -1,13 +1,14 @@ -use pagetop::{prelude::*, core::app::AppTrait}; +use pagetop::prelude::*; struct Drust; impl AppTrait for Drust { - fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { + fn enable_modules(&self) -> Vec<&'static dyn ModuleTrait> { vec![ &pagetop_admin::Admin, &pagetop_user::User, &pagetop_node::Node, + &demopage::Demopage, ] } } diff --git a/pagetop/src/core/app/application.rs b/pagetop/src/core/app/application.rs index 01af2c5b..3069aa19 100644 --- a/pagetop/src/core/app/application.rs +++ b/pagetop/src/core/app/application.rs @@ -5,13 +5,14 @@ use super::AppTrait; use std::io::Error; use actix_web::middleware::normalize::{NormalizePath, TrailingSlash}; +use actix_web::dev::Server; pub struct Application { - server: super::Server, + server: Server, } impl Application { - pub async fn prepare(brrrz: impl AppTrait) -> Result { + pub async fn prepare(app: impl AppTrait) -> Result { // Rótulo de presentación. super::banner::print_on_startup(); @@ -25,36 +26,30 @@ impl Application { #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] Lazy::force(&super::db::DBCONN); + // Habilita los módulos de la aplicación. + module::all::enable_modules(app.enable_modules()); + // Registra los temas predeterminados. - theme::register_themes(vec![ + theme::all::register_themes(vec![ &base::theme::aliner::Aliner, &base::theme::minimal::Minimal, &base::theme::bootsier::Bootsier, &base::theme::bulmix::Bulmix, ]); - theme::register_themes(brrrz.register_themes()); - - // Habilita los módulos predeterminados. - module::enable_modules(brrrz.enabled_modules()); - // Habilita el módulo de presentación de PageTop. - // Normalmente se sobrecargará en la función de inicio. - module::enable_module(&base::module::demopage::Demopage); + // Registra los temas de la aplicación. + theme::all::register_themes(app.themes()); // Registra las acciones de todos los módulos. module::all::register_hooks(); - // Ejecuta la función de inicio de la aplicación. - trace::info!("Calling application bootstrap"); - brrrz.bootstrap(); - /* - if let UsingBootstrap::Fn(bootstrap) = bootstrap { - let _ = &bootstrap(); - }*/ - - // Actualizaciones pendientes de la base de datos (opcional). + // Ejecuta actualizaciones pendientes de la base de datos (opcional). #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] module::all::run_migrations(); + // Ejecuta la función de inicio de la aplicación. + trace::info!("Calling application bootstrap"); + app.bootstrap(); + // Prepara el servidor web. let server = super::HttpServer::new(move || { super::App::new() @@ -72,7 +67,7 @@ impl Application { Ok(Self { server }) } - pub fn run(self) -> Result { + pub fn run(self) -> Result { Ok(self.server) } } diff --git a/pagetop/src/core/app/definition.rs b/pagetop/src/core/app/definition.rs index 7c13f9b0..4740d223 100644 --- a/pagetop/src/core/app/definition.rs +++ b/pagetop/src/core/app/definition.rs @@ -1,3 +1,4 @@ +use crate::base::module::demopage; use crate::core::module::ModuleTrait; use crate::core::theme::ThemeTrait; @@ -5,15 +6,17 @@ pub trait AppTrait: Send + Sync { fn bootstrap(&self) { } - fn enabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { + fn enable_modules(&self) -> Vec<&'static dyn ModuleTrait> { + vec![ + &demopage::Demopage, + ] + } + + fn disable_modules(&self) -> Vec<&'static dyn ModuleTrait> { vec![] } - fn disabled_modules(&self) -> Vec<&'static dyn ModuleTrait> { - vec![] - } - - fn register_themes(&self) -> Vec<&'static dyn ThemeTrait> { + fn themes(&self) -> Vec<&'static dyn ThemeTrait> { vec![] } } diff --git a/pagetop/src/core/app/mod.rs b/pagetop/src/core/app/mod.rs index 04feaf83..17bd0509 100644 --- a/pagetop/src/core/app/mod.rs +++ b/pagetop/src/core/app/mod.rs @@ -1,7 +1,6 @@ pub use actix_web::{ App, HttpRequest, HttpResponse, HttpServer, Responder, Result, http, web }; -use actix_web::dev::Server; mod banner; diff --git a/pagetop/src/core/component/assets.rs b/pagetop/src/core/component/assets.rs index 1274348d..563e33c9 100644 --- a/pagetop/src/core/component/assets.rs +++ b/pagetop/src/core/component/assets.rs @@ -4,7 +4,7 @@ use crate::html::{Markup, PreEscaped, html}; use crate::core::theme::*; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - match theme_by_single_name(&SETTINGS.app.theme) { + match all::theme_by_single_name(&SETTINGS.app.theme) { Some(theme) => theme, None => &base::theme::bootsier::Bootsier, } @@ -197,7 +197,7 @@ impl Assets { } pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); + self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); self } diff --git a/pagetop/src/core/module/all.rs b/pagetop/src/core/module/all.rs index ac5e8144..5131a878 100644 --- a/pagetop/src/core/module/all.rs +++ b/pagetop/src/core/module/all.rs @@ -18,11 +18,11 @@ static DISABLED_MODULES: Lazy>> = Lazy::new(|| { pub fn enable_modules(modules: Vec<&'static dyn ModuleTrait>) { for m in modules { - enable_module(m) + enable(m) } } -pub fn enable_module(module: &'static dyn ModuleTrait) { +fn enable(module: &'static dyn ModuleTrait) { let mut list: Vec<&dyn ModuleTrait> = Vec::new(); add_to(&mut list, module); list.reverse(); @@ -43,11 +43,11 @@ fn add_to(list: &mut Vec<&dyn ModuleTrait>, module: &'static dyn ModuleTrait) { } } } - +/* #[allow(unused_variables)] pub fn disable_module(module: &'static dyn ModuleTrait) { } - +*/ pub fn modules(cfg: &mut app::web::ServiceConfig) { for m in ENABLED_MODULES.read().unwrap().iter() { m.configure_service(cfg); diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module/mod.rs index 424595e3..e50144b5 100644 --- a/pagetop/src/core/module/mod.rs +++ b/pagetop/src/core/module/mod.rs @@ -5,8 +5,3 @@ pub use definition::{ }; pub(crate) mod all; -pub use all::{ - disable_module, - enable_module, - enable_modules, -}; diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/core/theme/all.rs index ba725b71..dc693e70 100644 --- a/pagetop/src/core/theme/all.rs +++ b/pagetop/src/core/theme/all.rs @@ -13,11 +13,11 @@ static THEMES: Lazy>> = Lazy::new(|| { pub fn register_themes(themes: Vec<&'static dyn ThemeTrait>) { for t in themes { - register_theme(t) + register(t) } } -pub fn register_theme(theme: &'static dyn ThemeTrait) { +fn register(theme: &'static dyn ThemeTrait) { let mut themes = THEMES.write().unwrap(); if !themes.iter().any(|t| t.handler() == theme.handler()) { trace::debug!("Registering theme \"{}\"", theme.single_name()); diff --git a/pagetop/src/core/theme/mod.rs b/pagetop/src/core/theme/mod.rs index 5a4b4060..391a0064 100644 --- a/pagetop/src/core/theme/mod.rs +++ b/pagetop/src/core/theme/mod.rs @@ -5,8 +5,3 @@ pub use definition::{ }; pub(crate) mod all; -pub use all::{ - register_theme, - register_themes, - theme_by_single_name, -}; diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 64da0481..c4081535 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -18,10 +18,9 @@ pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a base de datos. -pub mod core; // Main APIs for actions, components, modules and themes. +pub mod core; // Main APIs for app, components, hooks, modules and themes. pub mod response; // Tipos de respuestas web. -//pub mod app; // Aplicación y servidor web. pub mod base; // Base de componentes, módulos y temas. pub mod util; // Macros y funciones útiles. diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 0495bc70..d271980c 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -21,20 +21,18 @@ pub use crate::{ }; pub use crate::{hook_item, core::{ -// app::*, + app, component::*, hook::*, module::*, theme::*, }}; -pub use crate::core::app; +pub use crate::core::app::AppTrait; pub use crate::core::app::application::Application; pub use crate::response::page::*; -//pub use crate::app; -//pub use crate::app::application::{Application, UsingBootstrap}; - pub use crate::base::component::*; +pub use crate::base::module::demopage; pub use crate::util; From b3854fe393dbe7472a8eba6dace266ae60ed0645 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 8 May 2022 13:54:18 +0200 Subject: [PATCH 59/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drust/src/main.rs | 8 +++++++- pagetop/Cargo.toml | 2 +- pagetop/src/base/module/demopage/mod.rs | 1 - pagetop/src/core/app/application.rs | 1 - pagetop/src/prelude.rs | 6 ++---- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drust/src/main.rs b/drust/src/main.rs index 6b1f4543..4c210191 100644 --- a/drust/src/main.rs +++ b/drust/src/main.rs @@ -8,7 +8,13 @@ impl AppTrait for Drust { &pagetop_admin::Admin, &pagetop_user::User, &pagetop_node::Node, - &demopage::Demopage, + &pagetop::base::module::demopage::Demopage, + ] + } + + fn themes(&self) -> Vec<&'static dyn ThemeTrait> { + vec![ + &pagetop::base::theme::bulmix::Bulmix, ] } } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 912c3477..d044369c 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.12" +version = "0.0.14" edition = "2021" authors = [ diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 343b00a0..34fb8ba1 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -26,7 +26,6 @@ impl ModuleTrait for Demopage { async fn demo() -> app::Result { Page::new() - .using_theme("Bulmix") .with_title(l("page_title").as_str()) .add_to("content", hello_world()) .add_to("content", hello_world_original()) diff --git a/pagetop/src/core/app/application.rs b/pagetop/src/core/app/application.rs index 3069aa19..4cb18d39 100644 --- a/pagetop/src/core/app/application.rs +++ b/pagetop/src/core/app/application.rs @@ -34,7 +34,6 @@ impl Application { &base::theme::aliner::Aliner, &base::theme::minimal::Minimal, &base::theme::bootsier::Bootsier, - &base::theme::bulmix::Bulmix, ]); // Registra los temas de la aplicación. theme::all::register_themes(app.themes()); diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index d271980c..e9b8a396 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -1,10 +1,11 @@ //! Re-exporta recursos comunes. -// Macros. +// Macros, globals and helpers. pub use crate::{ args, concat_string, theme_static_files, + util, }; pub use crate::config::SETTINGS; @@ -33,6 +34,3 @@ pub use crate::core::app::application::Application; pub use crate::response::page::*; pub use crate::base::component::*; -pub use crate::base::module::demopage; - -pub use crate::util; From dda666e8890a13bfb30c0147649b34ba772c4536 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 9 May 2022 21:07:57 +0200 Subject: [PATCH 60/80] =?UTF-8?q?A=C3=B1ade=20componentes=20para=20cabecer?= =?UTF-8?q?as=20y=20p=C3=A1rrafos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/heading.rs | 186 ++++++++++++++++++++++++ pagetop/src/base/component/mod.rs | 8 + pagetop/src/base/component/paragraph.rs | 177 ++++++++++++++++++++++ pagetop/src/base/module/demopage/mod.rs | 26 ++-- pagetop/src/base/theme/bulmix/mod.rs | 29 ++++ 5 files changed, 414 insertions(+), 12 deletions(-) create mode 100644 pagetop/src/base/component/heading.rs create mode 100644 pagetop/src/base/component/paragraph.rs diff --git a/pagetop/src/base/component/heading.rs b/pagetop/src/base/component/heading.rs new file mode 100644 index 00000000..5023e611 --- /dev/null +++ b/pagetop/src/base/component/heading.rs @@ -0,0 +1,186 @@ +use crate::prelude::*; + +pub const HEADING_COMPONENT: &str = "pagetop::component::heading"; + +pub enum HeadingType { + H1(String), + H2(String), + H3(String), + H4(String), + H5(String), + H6(String), +} + +pub enum HeadingDisplay { + XxLarge, + Large, + Normal, + Medium, + Small, + XxSmall, +} + +pub struct Heading { + renderable: fn() -> bool, + weight : isize, + heading : HeadingType, + display : HeadingDisplay, + id : OptIden, + classes : Classes, + template : String, +} + +impl ComponentTrait for Heading { + fn new() -> Self { + Heading { + renderable: render_always, + weight : 0, + heading : HeadingType::H1("".to_owned()), + display : HeadingDisplay::Normal, + id : OptIden::new(), + classes : Classes::new(), + template : "default".to_owned(), + } + } + + fn handler(&self) -> &'static str { + HEADING_COMPONENT + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> isize { + self.weight + } + + fn default_render(&self, _: &mut Assets) -> Markup { + html! { @match &self.heading() { + HeadingType::H1(text) => h1 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H2(text) => h2 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H3(text) => h3 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H4(text) => h4 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H5(text) => h5 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H6(text) => h6 id=[self.id()] class=[self.classes()] { (text) }, + }} + } + + fn as_ref_any(&self) -> &dyn AnyComponent { + self + } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } +} + +impl Heading { + pub fn with(heading: HeadingType) -> Self { + Heading::new().with_heading(heading) + } + + // Heading BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.alter_renderable(renderable); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.alter_weight(weight); + self + } + + pub fn with_heading(mut self, heading: HeadingType) -> Self { + self.alter_heading(heading); + self + } + + pub fn with_display(mut self, display: HeadingDisplay) -> Self { + self.alter_display(display); + self + } + + pub fn with_id(mut self, id: &str) -> Self { + self.alter_id(id); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Heading ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_heading(&mut self, heading: HeadingType) -> &mut Self { + self.heading = heading; + self + } + + pub fn alter_display(&mut self, display: HeadingDisplay) -> &mut Self { + self.display = display; + self.classes.alter(match &self.display() { + HeadingDisplay::XxLarge => "display-2", + HeadingDisplay::Large => "display-3", + HeadingDisplay::Normal => "", + HeadingDisplay::Medium => "display-4", + HeadingDisplay::Small => "display-5", + HeadingDisplay::XxSmall => "display-6", + }, ClassesOp::SetDefault); + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { + self.template = template.to_owned(); + self + } + + // Paragraph GETTERS. + + pub fn heading(&self) -> &HeadingType { + &self.heading + } + + pub fn display(&self) -> &HeadingDisplay { + &self.display + } + + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index 14759dc8..986ba6f5 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -9,6 +9,14 @@ mod chunck; pub use chunck::{ CHUNCK_COMPONENT, Chunck }; +mod heading; +pub use heading::{ + HEADING_COMPONENT, Heading, HeadingDisplay, HeadingType +}; +mod paragraph; +pub use paragraph::{ + PARAGRAPH_COMPONENT, Paragraph, ParagraphDisplay +}; mod block; pub use block::{ BLOCK_COMPONENT, Block diff --git a/pagetop/src/base/component/paragraph.rs b/pagetop/src/base/component/paragraph.rs new file mode 100644 index 00000000..1cf7c01b --- /dev/null +++ b/pagetop/src/base/component/paragraph.rs @@ -0,0 +1,177 @@ +use crate::prelude::*; + +pub const PARAGRAPH_COMPONENT: &str = "pagetop::component::paragraph"; + +pub enum ParagraphDisplay { + XxLarge, + Large, + MediumPlus, + Normal, + Medium, + Small, + XxSmall, +} + +pub struct Paragraph { + renderable: fn() -> bool, + weight : isize, + html : Markup, + display : ParagraphDisplay, + id : OptIden, + classes : Classes, + template : String, +} + +impl ComponentTrait for Paragraph { + fn new() -> Self { + Paragraph { + renderable: render_always, + weight : 0, + html : html! {}, + display : ParagraphDisplay::Normal, + id : OptIden::new(), + classes : Classes::new(), + template : "default".to_owned(), + } + } + + fn handler(&self) -> &'static str { + PARAGRAPH_COMPONENT + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> isize { + self.weight + } + + fn default_render(&self, _: &mut Assets) -> Markup { + html! { + p id=[self.id()] class=[self.classes()] { (*self.html()) } + } + } + + fn as_ref_any(&self) -> &dyn AnyComponent { + self + } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } +} + +impl Paragraph { + pub fn with(html: Markup) -> Self { + Paragraph::new().with_html(html) + } + + // Paragraph BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.alter_renderable(renderable); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.alter_weight(weight); + self + } + + pub fn with_html(mut self, html: Markup) -> Self { + self.alter_html(html); + self + } + + pub fn with_display(mut self, display: ParagraphDisplay) -> Self { + self.alter_display(display); + self + } + + pub fn with_id(mut self, id: &str) -> Self { + self.alter_id(id); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Paragraph ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_html(&mut self, html: Markup) -> &mut Self { + self.html = html; + self + } + + pub fn alter_display(&mut self, display: ParagraphDisplay) -> &mut Self { + self.display = display; + self.classes.alter( + match &self.display() { + ParagraphDisplay::XxLarge => "fs-1", + ParagraphDisplay::Large => "fs-2", + ParagraphDisplay::MediumPlus => "fs-3", + ParagraphDisplay::Normal => "", + ParagraphDisplay::Medium => "fs-4", + ParagraphDisplay::Small => "fs-5", + ParagraphDisplay::XxSmall => "fs-6", + }, + ClassesOp::SetDefault + ); + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { + self.template = template.to_owned(); + self + } + + // Paragraph GETTERS. + + pub fn html(&self) -> &Markup { + &self.html + } + + pub fn display(&self) -> &ParagraphDisplay { + &self.display + } + + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 34fb8ba1..41c398c0 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -41,22 +41,24 @@ fn hello_world() -> Container { .add(grid::Row::new() .add_column(grid::Column::new() .add(Chunck::with(html! { - div class="section-title" { + div class="area-title" { (t("welcome_to", &args![ "app" => SETTINGS.app.name.as_str() ])) } - h1 class="h1-large" { - (l("page_title")) - } - p class="p-large" { - (e("welcome_intro", &args![ - "app" => format!( - "{}", - &SETTINGS.app.name - ) - ])) - } + })) + .add(Heading::with(HeadingType::H1( + l("page_title")) + ).with_display(HeadingDisplay::Large)) + .add(Paragraph::with(html! { + (e("welcome_intro", &args![ + "app" => format!( + "{}", + &SETTINGS.app.name + ) + ])) + }).with_display(ParagraphDisplay::Large)) + .add(Chunck::with(html! { p { (e("welcome_pagetop", &args![ "pagetop" => "PageTop" diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index e047b214..7bdb0890 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -36,6 +36,35 @@ impl ThemeTrait for Bulmix { _assets: &mut Assets ) { match component.handler() { + HEADING_COMPONENT => { + let h = component_mut::(component); + h.alter_classes( + concat_string!("title ", match h.display() { + HeadingDisplay::XxLarge => "is-1", + HeadingDisplay::Large => "is-2", + HeadingDisplay::Normal => "", + HeadingDisplay::Medium => "is-3", + HeadingDisplay::Small => "is-4", + HeadingDisplay::XxSmall => "is-5", + }).as_str(), + ClassesOp::SetDefault + ); + }, + PARAGRAPH_COMPONENT => { + let p = component_mut::(component); + p.alter_classes( + match p.display() { + ParagraphDisplay::XxLarge => "is-size-2", + ParagraphDisplay::Large => "is-size-3", + ParagraphDisplay::MediumPlus => "is-size-4", + ParagraphDisplay::Normal => "", + ParagraphDisplay::Medium => "is-size-5", + ParagraphDisplay::Small => "is-size-6", + ParagraphDisplay::XxSmall => "is-size-7", + }, + ClassesOp::SetDefault + ); + }, grid::ROW_COMPONENT => { let row = component_mut::(component); row.alter_classes("columns", ClassesOp::SetDefault); From 075c546fd55c799e9432ed797ab9f1bd5b924aa9 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 13 May 2022 16:25:11 +0200 Subject: [PATCH 61/80] =?UTF-8?q?A=C3=B1ade=20componentes=20para=20enlaces?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/anchor.rs | 227 ++++++++++++++++++++++++ pagetop/src/base/component/heading.rs | 77 +++++--- pagetop/src/base/component/mod.rs | 4 + pagetop/src/base/component/paragraph.rs | 23 +-- pagetop/src/base/module/demopage/mod.rs | 35 ++-- pagetop/src/base/theme/bulmix/mod.rs | 48 ++--- pagetop/src/html/classes.rs | 5 + 7 files changed, 338 insertions(+), 81 deletions(-) create mode 100644 pagetop/src/base/component/anchor.rs diff --git a/pagetop/src/base/component/anchor.rs b/pagetop/src/base/component/anchor.rs new file mode 100644 index 00000000..d0534694 --- /dev/null +++ b/pagetop/src/base/component/anchor.rs @@ -0,0 +1,227 @@ +use crate::prelude::*; + +pub const ANCHOR_COMPONENT: &str = "pagetop::component::anchor"; + +pub enum AnchorType { + Button, + Link, + Location, +} + +pub enum AnchorTarget { + Blank, + Context(String), + Default, + Parent, + Top, +} + +pub struct Anchor { + renderable : fn() -> bool, + weight : isize, + anchor_type: AnchorType, + href : OptAttr, + html : Markup, + target : AnchorTarget, + id : OptIden, + classes : Classes, + template : String, +} + +impl ComponentTrait for Anchor { + fn new() -> Self { + Anchor { + renderable : render_always, + weight : 0, + anchor_type: AnchorType::Link, + href : OptAttr::new(), + html : html! {}, + target : AnchorTarget::Default, + id : OptIden::new(), + classes : Classes::new(), + template : "default".to_owned(), + } + } + + fn handler(&self) -> &'static str { + ANCHOR_COMPONENT + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> isize { + self.weight + } + + fn default_render(&self, _: &mut Assets) -> Markup { + let target = match &self.target() { + AnchorTarget::Blank => Some("_blank"), + AnchorTarget::Context(name) => Some(name.as_str()), + AnchorTarget::Parent => Some("_parent"), + AnchorTarget::Top => Some("_top"), + _ => None, + }; + html! { + a + id=[self.id()] + class=[self.classes()] + href=[self.href()] + target=[target] + { + (*self.html()) + } + } + } + + fn as_ref_any(&self) -> &dyn AnyComponent { + self + } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } +} + +impl Anchor { + pub fn link(href: &str, html: Markup) -> Self { + Anchor::new().with_href(href).with_html(html) + } + + pub fn button(href: &str, html: Markup) -> Self { + Anchor::new().with_type(AnchorType::Button).with_href(href).with_html(html) + } + + pub fn location(id: &str) -> Self { + Anchor::new().with_type(AnchorType::Location).with_id(id) + } + + // Anchor BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.alter_renderable(renderable); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.alter_weight(weight); + self + } + + pub fn with_type(mut self, anchor_type: AnchorType) -> Self { + self.alter_type(anchor_type); + self + } + + pub fn with_href(mut self, href: &str) -> Self { + self.alter_href(href); + self + } + + pub fn with_html(mut self, html: Markup) -> Self { + self.alter_html(html); + self + } + + pub fn with_target(mut self, target: AnchorTarget) -> Self { + self.alter_target(target); + self + } + + pub fn with_id(mut self, id: &str) -> Self { + self.alter_id(id); + self + } + + pub fn with_classes(mut self, classes: &str, op: ClassesOp) -> Self { + self.alter_classes(classes, op); + self + } + + pub fn using_template(mut self, template: &str) -> Self { + self.alter_template(template); + self + } + + // Anchor ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_type(&mut self, anchor_type: AnchorType) -> &mut Self { + self.anchor_type = anchor_type; + self.classes.alter(match self.anchor_type { + AnchorType::Button => "btn btn-primary", + _ => "", + }, ClassesOp::SetDefault); + self + } + + pub fn alter_href(&mut self, href: &str) -> &mut Self { + self.href.with_value(href); + self + } + + pub fn alter_html(&mut self, html: Markup) -> &mut Self { + self.html = html; + self + } + + pub fn alter_target(&mut self, target: AnchorTarget) -> &mut Self { + self.target = target; + self + } + + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.with_value(id); + self + } + + pub fn alter_classes(&mut self, classes: &str, op: ClassesOp) -> &mut Self { + self.classes.alter(classes, op); + self + } + + pub fn alter_template(&mut self, template: &str) -> &mut Self { + self.template = template.to_owned(); + self + } + + // Anchor GETTERS. + + pub fn anchor_type(&self) -> &AnchorType { + &self.anchor_type + } + + pub fn href(&self) -> &Option { + self.href.option() + } + + pub fn html(&self) -> &Markup { + &self.html + } + + pub fn target(&self) -> &AnchorTarget { + &self.target + } + + pub fn id(&self) -> &Option { + self.id.option() + } + + pub fn classes(&self) -> &Option { + self.classes.option() + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} diff --git a/pagetop/src/base/component/heading.rs b/pagetop/src/base/component/heading.rs index 5023e611..fa17ca7e 100644 --- a/pagetop/src/base/component/heading.rs +++ b/pagetop/src/base/component/heading.rs @@ -2,28 +2,22 @@ use crate::prelude::*; pub const HEADING_COMPONENT: &str = "pagetop::component::heading"; -pub enum HeadingType { - H1(String), - H2(String), - H3(String), - H4(String), - H5(String), - H6(String), -} +pub enum HeadingType { H1, H2, H3, H4, H5, H6 } pub enum HeadingDisplay { XxLarge, Large, - Normal, Medium, Small, XxSmall, + Normal, } pub struct Heading { renderable: fn() -> bool, weight : isize, heading : HeadingType, + html : Markup, display : HeadingDisplay, id : OptIden, classes : Classes, @@ -35,7 +29,8 @@ impl ComponentTrait for Heading { Heading { renderable: render_always, weight : 0, - heading : HeadingType::H1("".to_owned()), + heading : HeadingType::H1, + html : html! {}, display : HeadingDisplay::Normal, id : OptIden::new(), classes : Classes::new(), @@ -57,12 +52,12 @@ impl ComponentTrait for Heading { fn default_render(&self, _: &mut Assets) -> Markup { html! { @match &self.heading() { - HeadingType::H1(text) => h1 id=[self.id()] class=[self.classes()] { (text) }, - HeadingType::H2(text) => h2 id=[self.id()] class=[self.classes()] { (text) }, - HeadingType::H3(text) => h3 id=[self.id()] class=[self.classes()] { (text) }, - HeadingType::H4(text) => h4 id=[self.id()] class=[self.classes()] { (text) }, - HeadingType::H5(text) => h5 id=[self.id()] class=[self.classes()] { (text) }, - HeadingType::H6(text) => h6 id=[self.id()] class=[self.classes()] { (text) }, + HeadingType::H1 => h1 id=[self.id()] class=[self.classes()] { (*self.html()) }, + HeadingType::H2 => h2 id=[self.id()] class=[self.classes()] { (*self.html()) }, + HeadingType::H3 => h3 id=[self.id()] class=[self.classes()] { (*self.html()) }, + HeadingType::H4 => h4 id=[self.id()] class=[self.classes()] { (*self.html()) }, + HeadingType::H5 => h5 id=[self.id()] class=[self.classes()] { (*self.html()) }, + HeadingType::H6 => h6 id=[self.id()] class=[self.classes()] { (*self.html()) }, }} } @@ -76,8 +71,28 @@ impl ComponentTrait for Heading { } impl Heading { - pub fn with(heading: HeadingType) -> Self { - Heading::new().with_heading(heading) + pub fn h1(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H1).with_html(html) + } + + pub fn h2(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H2).with_html(html) + } + + pub fn h3(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H3).with_html(html) + } + + pub fn h4(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H4).with_html(html) + } + + pub fn h5(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H5).with_html(html) + } + + pub fn h6(html: Markup) -> Self { + Heading::new().with_heading(HeadingType::H6).with_html(html) } // Heading BUILDER. @@ -97,6 +112,11 @@ impl Heading { self } + pub fn with_html(mut self, html: Markup) -> Self { + self.alter_html(html); + self + } + pub fn with_display(mut self, display: HeadingDisplay) -> Self { self.alter_display(display); self @@ -134,15 +154,20 @@ impl Heading { self } + pub fn alter_html(&mut self, html: Markup) -> &mut Self { + self.html = html; + self + } + pub fn alter_display(&mut self, display: HeadingDisplay) -> &mut Self { self.display = display; self.classes.alter(match &self.display() { - HeadingDisplay::XxLarge => "display-2", - HeadingDisplay::Large => "display-3", - HeadingDisplay::Normal => "", - HeadingDisplay::Medium => "display-4", - HeadingDisplay::Small => "display-5", - HeadingDisplay::XxSmall => "display-6", + HeadingDisplay::XxLarge => "display-2", + HeadingDisplay::Large => "display-3", + HeadingDisplay::Medium => "display-4", + HeadingDisplay::Small => "display-5", + HeadingDisplay::XxSmall => "display-6", + HeadingDisplay::Normal => "", }, ClassesOp::SetDefault); self } @@ -168,6 +193,10 @@ impl Heading { &self.heading } + pub fn html(&self) -> &Markup { + &self.html + } + pub fn display(&self) -> &HeadingDisplay { &self.display } diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component/mod.rs index 986ba6f5..22caca38 100644 --- a/pagetop/src/base/component/mod.rs +++ b/pagetop/src/base/component/mod.rs @@ -17,6 +17,10 @@ mod paragraph; pub use paragraph::{ PARAGRAPH_COMPONENT, Paragraph, ParagraphDisplay }; +mod anchor; +pub use anchor::{ + ANCHOR_COMPONENT, Anchor, AnchorTarget, AnchorType +}; mod block; pub use block::{ BLOCK_COMPONENT, Block diff --git a/pagetop/src/base/component/paragraph.rs b/pagetop/src/base/component/paragraph.rs index 1cf7c01b..025d9565 100644 --- a/pagetop/src/base/component/paragraph.rs +++ b/pagetop/src/base/component/paragraph.rs @@ -5,11 +5,10 @@ pub const PARAGRAPH_COMPONENT: &str = "pagetop::component::paragraph"; pub enum ParagraphDisplay { XxLarge, Large, - MediumPlus, - Normal, Medium, Small, XxSmall, + Normal, } pub struct Paragraph { @@ -123,18 +122,14 @@ impl Paragraph { pub fn alter_display(&mut self, display: ParagraphDisplay) -> &mut Self { self.display = display; - self.classes.alter( - match &self.display() { - ParagraphDisplay::XxLarge => "fs-1", - ParagraphDisplay::Large => "fs-2", - ParagraphDisplay::MediumPlus => "fs-3", - ParagraphDisplay::Normal => "", - ParagraphDisplay::Medium => "fs-4", - ParagraphDisplay::Small => "fs-5", - ParagraphDisplay::XxSmall => "fs-6", - }, - ClassesOp::SetDefault - ); + self.classes.alter(match &self.display() { + ParagraphDisplay::XxLarge => "fs-2", + ParagraphDisplay::Large => "fs-3", + ParagraphDisplay::Medium => "fs-4", + ParagraphDisplay::Small => "fs-5", + ParagraphDisplay::XxSmall => "fs-6", + ParagraphDisplay::Normal => "", + }, ClassesOp::SetDefault); self } diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage/mod.rs index 41c398c0..f8753638 100644 --- a/pagetop/src/base/module/demopage/mod.rs +++ b/pagetop/src/base/module/demopage/mod.rs @@ -40,30 +40,27 @@ fn hello_world() -> Container { Container::header() .add(grid::Row::new() .add_column(grid::Column::new() - .add(Chunck::with(html! { - div class="area-title" { - (t("welcome_to", &args![ - "app" => SETTINGS.app.name.as_str() - ])) - } + .add(Heading::h1(html! { + (l("page_title")) + }).with_display(HeadingDisplay::Large)) + .add(Paragraph::with(html! { + (t("welcome_to", &args![ + "app" => SETTINGS.app.name.as_str() + ])) })) - .add(Heading::with(HeadingType::H1( - l("page_title")) - ).with_display(HeadingDisplay::Large)) .add(Paragraph::with(html! { (e("welcome_intro", &args![ - "app" => format!( - "{}", - &SETTINGS.app.name - ) + "app" => format!("{}", &SETTINGS.app.name) ])) - }).with_display(ParagraphDisplay::Large)) + }).with_display(ParagraphDisplay::Small)) + .add(Paragraph::with(html! { + (e("welcome_pagetop", &args![ + "pagetop" => "PageTop" + ])) + })) + .add(Anchor::button("#", html! { ("Offered services") })) + .add(Anchor::button("#", html! { ("Get quote") })) .add(Chunck::with(html! { - p { - (e("welcome_pagetop", &args![ - "pagetop" => "PageTop" - ])) - } a class="btn-solid-lg" href="#services" { "Offered services" } diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix/mod.rs index 7bdb0890..b4a360fb 100644 --- a/pagetop/src/base/theme/bulmix/mod.rs +++ b/pagetop/src/base/theme/bulmix/mod.rs @@ -38,32 +38,32 @@ impl ThemeTrait for Bulmix { match component.handler() { HEADING_COMPONENT => { let h = component_mut::(component); - h.alter_classes( - concat_string!("title ", match h.display() { - HeadingDisplay::XxLarge => "is-1", - HeadingDisplay::Large => "is-2", - HeadingDisplay::Normal => "", - HeadingDisplay::Medium => "is-3", - HeadingDisplay::Small => "is-4", - HeadingDisplay::XxSmall => "is-5", - }).as_str(), - ClassesOp::SetDefault - ); + h.alter_classes(concat_string!("title ", match h.display() { + HeadingDisplay::XxLarge => "is-1", + HeadingDisplay::Large => "is-2", + HeadingDisplay::Medium => "is-3", + HeadingDisplay::Small => "is-4", + HeadingDisplay::XxSmall => "is-5", + HeadingDisplay::Normal => "", + }).as_str(), ClassesOp::SetDefault); }, PARAGRAPH_COMPONENT => { let p = component_mut::(component); - p.alter_classes( - match p.display() { - ParagraphDisplay::XxLarge => "is-size-2", - ParagraphDisplay::Large => "is-size-3", - ParagraphDisplay::MediumPlus => "is-size-4", - ParagraphDisplay::Normal => "", - ParagraphDisplay::Medium => "is-size-5", - ParagraphDisplay::Small => "is-size-6", - ParagraphDisplay::XxSmall => "is-size-7", - }, - ClassesOp::SetDefault - ); + p.alter_classes(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 => "", + }, ClassesOp::SetDefault); + }, + ANCHOR_COMPONENT => { + let a = component_mut::(component); + a.alter_classes(match a.anchor_type() { + AnchorType::Button => "button is-primary", + _ => "", + }, ClassesOp::SetDefault); }, grid::ROW_COMPONENT => { let row = component_mut::(component); @@ -71,7 +71,7 @@ impl ThemeTrait for Bulmix { }, grid::COLUMN_COMPONENT => { let col = component_mut::(component); - col.alter_classes("column", ClassesOp::SetDefault); + col.alter_classes("column content", ClassesOp::SetDefault); }, _ => {}, } diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index aa629aaf..0623baa2 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -8,6 +8,7 @@ pub enum ClassesOp { Replace(&'static str), Reset, SetDefault, + SetDefaultIfEmpty, } pub struct Classes { @@ -75,6 +76,10 @@ impl Classes { ClassesOp::Reset => self.added = classes.to_owned(), ClassesOp::SetDefault => self.default = classes.to_owned(), + + ClassesOp::SetDefaultIfEmpty => if self.default.is_empty() { + self.default = classes.to_owned() + }, } self.option = Some(concat_string!(self.default, " ", self.added).trim().to_owned()); self From 7d06cdec19ebd1f2a46b3c44c00d5334fde87e0a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 13 May 2022 18:59:33 +0200 Subject: [PATCH 62/80] =?UTF-8?q?Actualiza=20estructura=20de=20archivos=20?= =?UTF-8?q?a=20nueva=20edici=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/{migration/mod.rs => migration.rs} | 0 .../src/{migration/mod.rs => migration.rs} | 0 pagetop/src/{base/mod.rs => base.rs} | 0 .../base/{component/mod.rs => component.rs} | 0 .../base/component/{form/mod.rs => form.rs} | 0 .../base/component/{grid/mod.rs => grid.rs} | 0 pagetop/src/base/{module/mod.rs => module.rs} | 0 .../module/{demopage/mod.rs => demopage.rs} | 0 pagetop/src/base/{theme/mod.rs => theme.rs} | 0 .../base/theme/{aliner/mod.rs => aliner.rs} | 0 .../theme/{bootsier/mod.rs => bootsier.rs} | 0 .../base/theme/{bulmix/mod.rs => bulmix.rs} | 0 .../base/theme/{minimal/mod.rs => minimal.rs} | 0 pagetop/src/{core/mod.rs => core.rs} | 0 pagetop/src/core/{app/mod.rs => app.rs} | 0 .../src/core/app/{banner/mod.rs => banner.rs} | 31 ++----------------- pagetop/src/core/app/banner/figfont.rs | 30 ++++++++++++++++++ .../core/{component/mod.rs => component.rs} | 0 pagetop/src/core/{hook/mod.rs => hook.rs} | 0 pagetop/src/core/{module/mod.rs => module.rs} | 0 pagetop/src/core/{theme/mod.rs => theme.rs} | 0 pagetop/src/{html/mod.rs => html.rs} | 0 pagetop/src/{response/mod.rs => response.rs} | 0 pagetop/src/response/{page/mod.rs => page.rs} | 4 +-- .../response/page/{page.rs => definition.rs} | 0 25 files changed, 35 insertions(+), 30 deletions(-) rename pagetop-node/src/{migration/mod.rs => migration.rs} (100%) rename pagetop-user/src/{migration/mod.rs => migration.rs} (100%) rename pagetop/src/{base/mod.rs => base.rs} (100%) rename pagetop/src/base/{component/mod.rs => component.rs} (100%) rename pagetop/src/base/component/{form/mod.rs => form.rs} (100%) rename pagetop/src/base/component/{grid/mod.rs => grid.rs} (100%) rename pagetop/src/base/{module/mod.rs => module.rs} (100%) rename pagetop/src/base/module/{demopage/mod.rs => demopage.rs} (100%) rename pagetop/src/base/{theme/mod.rs => theme.rs} (100%) rename pagetop/src/base/theme/{aliner/mod.rs => aliner.rs} (100%) rename pagetop/src/base/theme/{bootsier/mod.rs => bootsier.rs} (100%) rename pagetop/src/base/theme/{bulmix/mod.rs => bulmix.rs} (100%) rename pagetop/src/base/theme/{minimal/mod.rs => minimal.rs} (100%) rename pagetop/src/{core/mod.rs => core.rs} (100%) rename pagetop/src/core/{app/mod.rs => app.rs} (100%) rename pagetop/src/core/app/{banner/mod.rs => banner.rs} (52%) create mode 100644 pagetop/src/core/app/banner/figfont.rs rename pagetop/src/core/{component/mod.rs => component.rs} (100%) rename pagetop/src/core/{hook/mod.rs => hook.rs} (100%) rename pagetop/src/core/{module/mod.rs => module.rs} (100%) rename pagetop/src/core/{theme/mod.rs => theme.rs} (100%) rename pagetop/src/{html/mod.rs => html.rs} (100%) rename pagetop/src/{response/mod.rs => response.rs} (100%) rename pagetop/src/response/{page/mod.rs => page.rs} (66%) rename pagetop/src/response/page/{page.rs => definition.rs} (100%) diff --git a/pagetop-node/src/migration/mod.rs b/pagetop-node/src/migration.rs similarity index 100% rename from pagetop-node/src/migration/mod.rs rename to pagetop-node/src/migration.rs diff --git a/pagetop-user/src/migration/mod.rs b/pagetop-user/src/migration.rs similarity index 100% rename from pagetop-user/src/migration/mod.rs rename to pagetop-user/src/migration.rs diff --git a/pagetop/src/base/mod.rs b/pagetop/src/base.rs similarity index 100% rename from pagetop/src/base/mod.rs rename to pagetop/src/base.rs diff --git a/pagetop/src/base/component/mod.rs b/pagetop/src/base/component.rs similarity index 100% rename from pagetop/src/base/component/mod.rs rename to pagetop/src/base/component.rs diff --git a/pagetop/src/base/component/form/mod.rs b/pagetop/src/base/component/form.rs similarity index 100% rename from pagetop/src/base/component/form/mod.rs rename to pagetop/src/base/component/form.rs diff --git a/pagetop/src/base/component/grid/mod.rs b/pagetop/src/base/component/grid.rs similarity index 100% rename from pagetop/src/base/component/grid/mod.rs rename to pagetop/src/base/component/grid.rs diff --git a/pagetop/src/base/module/mod.rs b/pagetop/src/base/module.rs similarity index 100% rename from pagetop/src/base/module/mod.rs rename to pagetop/src/base/module.rs diff --git a/pagetop/src/base/module/demopage/mod.rs b/pagetop/src/base/module/demopage.rs similarity index 100% rename from pagetop/src/base/module/demopage/mod.rs rename to pagetop/src/base/module/demopage.rs diff --git a/pagetop/src/base/theme/mod.rs b/pagetop/src/base/theme.rs similarity index 100% rename from pagetop/src/base/theme/mod.rs rename to pagetop/src/base/theme.rs diff --git a/pagetop/src/base/theme/aliner/mod.rs b/pagetop/src/base/theme/aliner.rs similarity index 100% rename from pagetop/src/base/theme/aliner/mod.rs rename to pagetop/src/base/theme/aliner.rs diff --git a/pagetop/src/base/theme/bootsier/mod.rs b/pagetop/src/base/theme/bootsier.rs similarity index 100% rename from pagetop/src/base/theme/bootsier/mod.rs rename to pagetop/src/base/theme/bootsier.rs diff --git a/pagetop/src/base/theme/bulmix/mod.rs b/pagetop/src/base/theme/bulmix.rs similarity index 100% rename from pagetop/src/base/theme/bulmix/mod.rs rename to pagetop/src/base/theme/bulmix.rs diff --git a/pagetop/src/base/theme/minimal/mod.rs b/pagetop/src/base/theme/minimal.rs similarity index 100% rename from pagetop/src/base/theme/minimal/mod.rs rename to pagetop/src/base/theme/minimal.rs diff --git a/pagetop/src/core/mod.rs b/pagetop/src/core.rs similarity index 100% rename from pagetop/src/core/mod.rs rename to pagetop/src/core.rs diff --git a/pagetop/src/core/app/mod.rs b/pagetop/src/core/app.rs similarity index 100% rename from pagetop/src/core/app/mod.rs rename to pagetop/src/core/app.rs diff --git a/pagetop/src/core/app/banner/mod.rs b/pagetop/src/core/app/banner.rs similarity index 52% rename from pagetop/src/core/app/banner/mod.rs rename to pagetop/src/core/app/banner.rs index 1cce7146..a4dfd5b3 100644 --- a/pagetop/src/core/app/banner/mod.rs +++ b/pagetop/src/core/app/banner.rs @@ -1,35 +1,10 @@ -use crate::Lazy; +mod figfont; +use figfont::FIGFONT; + use crate::config::SETTINGS; -use figlet_rs::FIGfont; use substring::Substring; -static FIGFONT: Lazy = Lazy::new(|| { - let slant = include_str!("slant.flf"); - let small = include_str!("small.flf"); - let speed = include_str!("speed.flf"); - let starwars = include_str!("starwars.flf"); - - FIGfont::from_content( - match SETTINGS.app.startup_banner.to_lowercase().as_str() { - "off" => slant, - "slant" => slant, - "small" => small, - "speed" => speed, - "starwars" => starwars, - _ => { - println!( - "\n FIGfont \"{}\" not found for banner. {}. {}.", - SETTINGS.app.startup_banner, - "Using \"Slant\"", - "Check the settings file", - ); - slant - } - } - ).unwrap() -}); - pub fn print_on_startup() { if SETTINGS.app.startup_banner.to_lowercase() != "off" { if let Some((term_width, _)) = term_size::dimensions() { diff --git a/pagetop/src/core/app/banner/figfont.rs b/pagetop/src/core/app/banner/figfont.rs new file mode 100644 index 00000000..8fe0a4e7 --- /dev/null +++ b/pagetop/src/core/app/banner/figfont.rs @@ -0,0 +1,30 @@ +use crate::Lazy; +use crate::config::SETTINGS; + +use figlet_rs::FIGfont; + +pub static FIGFONT: Lazy = Lazy::new(|| { + let slant = include_str!("slant.flf"); + let small = include_str!("small.flf"); + let speed = include_str!("speed.flf"); + let starwars = include_str!("starwars.flf"); + + FIGfont::from_content( + match SETTINGS.app.startup_banner.to_lowercase().as_str() { + "off" => slant, + "slant" => slant, + "small" => small, + "speed" => speed, + "starwars" => starwars, + _ => { + println!( + "\n FIGfont \"{}\" not found for banner. {}. {}.", + SETTINGS.app.startup_banner, + "Using \"Slant\"", + "Check the settings file", + ); + slant + } + } + ).unwrap() +}); diff --git a/pagetop/src/core/component/mod.rs b/pagetop/src/core/component.rs similarity index 100% rename from pagetop/src/core/component/mod.rs rename to pagetop/src/core/component.rs diff --git a/pagetop/src/core/hook/mod.rs b/pagetop/src/core/hook.rs similarity index 100% rename from pagetop/src/core/hook/mod.rs rename to pagetop/src/core/hook.rs diff --git a/pagetop/src/core/module/mod.rs b/pagetop/src/core/module.rs similarity index 100% rename from pagetop/src/core/module/mod.rs rename to pagetop/src/core/module.rs diff --git a/pagetop/src/core/theme/mod.rs b/pagetop/src/core/theme.rs similarity index 100% rename from pagetop/src/core/theme/mod.rs rename to pagetop/src/core/theme.rs diff --git a/pagetop/src/html/mod.rs b/pagetop/src/html.rs similarity index 100% rename from pagetop/src/html/mod.rs rename to pagetop/src/html.rs diff --git a/pagetop/src/response/mod.rs b/pagetop/src/response.rs similarity index 100% rename from pagetop/src/response/mod.rs rename to pagetop/src/response.rs diff --git a/pagetop/src/response/page/mod.rs b/pagetop/src/response/page.rs similarity index 66% rename from pagetop/src/response/page/mod.rs rename to pagetop/src/response/page.rs index 82c5d7da..5f517471 100644 --- a/pagetop/src/response/page/mod.rs +++ b/pagetop/src/response/page.rs @@ -4,5 +4,5 @@ pub use hook::{ BeforeRenderPageHook, }; -mod page; -pub use page::Page; +mod definition; +pub use definition::Page; diff --git a/pagetop/src/response/page/page.rs b/pagetop/src/response/page/definition.rs similarity index 100% rename from pagetop/src/response/page/page.rs rename to pagetop/src/response/page/definition.rs From 9e5d6e1a7245b1d7fcfa1018d1f01923f74bbc1a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Fri, 13 May 2022 23:28:58 +0200 Subject: [PATCH 63/80] =?UTF-8?q?Corrige=20asignaci=C3=B3n=20err=C3=B3nea?= =?UTF-8?q?=20de=20identificador?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/menu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 450bc92e..6fa41268 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub const MENU_COMPONENT: &str = "pagetop::component::menu"; -pub const MENUITEM_COMPONENT: &str = "pagetop::component::menu"; +pub const MENUITEM_COMPONENT: &str = "pagetop::component::menu_item"; pub enum MenuItemType { Label(String), From 72f5144b7545b92fb0060a826daeda874e1ccd6d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 18:32:56 +0200 Subject: [PATCH 64/80] Modifica Assets por Context --- pagetop/src/base/component/anchor.rs | 2 +- pagetop/src/base/component/block.rs | 6 +- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 12 +- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 4 +- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 4 +- pagetop/src/base/component/grid/column.rs | 4 +- pagetop/src/base/component/grid/row.rs | 4 +- pagetop/src/base/component/heading.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 12 +- pagetop/src/base/component/paragraph.rs | 2 +- pagetop/src/base/theme/aliner.rs | 2 +- pagetop/src/base/theme/bootsier.rs | 2 +- pagetop/src/base/theme/bulmix.rs | 4 +- pagetop/src/core/component.rs | 6 +- pagetop/src/core/component/assets.rs | 302 ------------------ pagetop/src/core/component/context.rs | 148 +++++++++ pagetop/src/core/component/context/favicon.rs | 86 +++++ .../src/core/component/context/javascript.rs | 43 +++ .../src/core/component/context/stylesheet.rs | 29 ++ pagetop/src/core/component/definition.rs | 19 +- pagetop/src/core/component/holder.rs | 6 +- pagetop/src/core/component/hook.rs | 10 +- pagetop/src/core/theme/definition.rs | 10 +- pagetop/src/response/page/definition.rs | 18 +- 29 files changed, 375 insertions(+), 372 deletions(-) delete mode 100644 pagetop/src/core/component/assets.rs create mode 100644 pagetop/src/core/component/context.rs create mode 100644 pagetop/src/core/component/context/favicon.rs create mode 100644 pagetop/src/core/component/context/javascript.rs create mode 100644 pagetop/src/core/component/context/stylesheet.rs diff --git a/pagetop/src/base/component/anchor.rs b/pagetop/src/base/component/anchor.rs index d0534694..1d0ce8a1 100644 --- a/pagetop/src/base/component/anchor.rs +++ b/pagetop/src/base/component/anchor.rs @@ -55,7 +55,7 @@ impl ComponentTrait for Anchor { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { let target = match &self.target() { AnchorTarget::Blank => Some("_blank"), AnchorTarget::Context(name) => Some(name.as_str()), diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 4f120434..a37bc2ed 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -37,8 +37,8 @@ impl ComponentTrait for Block { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { - let id = assets.required_id::(self.id()); + fn default_render(&self, context: &mut Context) -> Markup { + let id = context.required_id::(self.id()); html! { div id=(id) class=[self.classes()] { @match self.title() { @@ -46,7 +46,7 @@ impl ComponentTrait for Block { None => {} } div class="block-body" { - (self.components().render(assets)) + (self.components().render(context)) } } } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index c7d8a978..fdbfe9ee 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -31,7 +31,7 @@ impl ComponentTrait for Chunck { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { html! { (*self.html()) } } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index e275f255..7be54148 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -41,39 +41,39 @@ impl ComponentTrait for Container { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { match self.container_type() { ContainerType::Header => html! { header id=[self.id()] class=[self.classes()] { div class=[self.inner_classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } }, ContainerType::Footer => html! { footer id=[self.id()] class=[self.classes()] { div class=[self.inner_classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } }, ContainerType::Main => html! { main id=[self.id()] class=[self.classes()] { div class=[self.inner_classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } }, ContainerType::Section => html! { section id=[self.id()] class=[self.classes()] { div class=[self.inner_classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } }, _ => html! { div id=[self.id()] class=[self.classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index fc7fe620..ad042b60 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -44,7 +44,7 @@ impl ComponentTrait for Button { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { let button_type = match self.button_type() { ButtonType::Button => "button", ButtonType::Reset => "reset", diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index eeb1d7aa..763a474a 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -52,7 +52,7 @@ impl ComponentTrait for Date { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("edit-", name)), None => None, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index dcf209b0..688eeeed 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -43,7 +43,7 @@ impl ComponentTrait for Form { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { let method = match self.method() { FormMethod::Get => None, FormMethod::Post => Some("post".to_owned()) @@ -56,7 +56,7 @@ impl ComponentTrait for Form { method=[method] accept-charset=[self.charset()] { - div { (self.elements().render(assets)) } + div { (self.elements().render(context)) } } } } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index c8d86131..91a2986f 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -25,7 +25,7 @@ impl ComponentTrait for Hidden { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("value-", name)), _ => None diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index d1614aa3..806be50a 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -62,14 +62,14 @@ impl ComponentTrait for Input { self.weight } - fn before_render(&mut self, _: &mut Assets) { + fn before_render(&mut self, _: &mut Context) { if let Some(name) = self.name() { let class = concat_string!("form-item-", name); self.alter_classes(class.as_str(), ClassesOp::AddFirst); } } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { let type_input = match self.input_type() { InputType::Email => "email", InputType::Password => "password", diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index a69edce7..b06faea2 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -35,10 +35,10 @@ impl ComponentTrait for Column { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { html! { div id=[self.id()] class=[self.classes()] { - (self.components().render(assets)) + (self.components().render(context)) } } } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 05fae1cf..0ffe3f08 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -35,10 +35,10 @@ impl ComponentTrait for Row { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { html! { div id=[self.id()] class=[self.classes()] { - (self.columns().render(assets)) + (self.columns().render(context)) } } } diff --git a/pagetop/src/base/component/heading.rs b/pagetop/src/base/component/heading.rs index fa17ca7e..eada3ea5 100644 --- a/pagetop/src/base/component/heading.rs +++ b/pagetop/src/base/component/heading.rs @@ -50,7 +50,7 @@ impl ComponentTrait for Heading { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { html! { @match &self.heading() { HeadingType::H1 => h1 id=[self.id()] class=[self.classes()] { (*self.html()) }, HeadingType::H2 => h2 id=[self.id()] class=[self.classes()] { (*self.html()) }, diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 300cafc2..5a3f16c6 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -35,7 +35,7 @@ impl ComponentTrait for Image { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { html! { img src=[self.source()] diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 6fa41268..c4a97a05 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -42,7 +42,7 @@ impl ComponentTrait for MenuItem { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { match self.item_type() { MenuItemType::Label(label) => html! { li class="label" { a href="#" { (label) } } @@ -62,7 +62,7 @@ impl ComponentTrait for MenuItem { li class="submenu" { a href="#" { (label) } ul { - (menu.items().render(assets)) + (menu.items().render(context)) } } }, @@ -206,8 +206,8 @@ impl ComponentTrait for Menu { self.weight } - fn default_render(&self, assets: &mut Assets) -> Markup { - assets + fn default_render(&self, context: &mut Context) -> Markup { + context .add_stylesheet(StyleSheet::source( "/theme/menu/css/menu.css?ver=1.1.1" )) @@ -219,10 +219,10 @@ impl ComponentTrait for Menu { )) .add_jquery(); - let id = assets.required_id::(self.id()); + let id = context.required_id::(self.id()); html! { ul id=(id) class=[self.classes()] { - (self.items().render(assets)) + (self.items().render(context)) } script type="text/javascript" defer { "jQuery(function(){jQuery('#" (id) "').smartmenus({" diff --git a/pagetop/src/base/component/paragraph.rs b/pagetop/src/base/component/paragraph.rs index 025d9565..d8e1ac4b 100644 --- a/pagetop/src/base/component/paragraph.rs +++ b/pagetop/src/base/component/paragraph.rs @@ -46,7 +46,7 @@ impl ComponentTrait for Paragraph { self.weight } - fn default_render(&self, _: &mut Assets) -> Markup { + fn default_render(&self, _: &mut Context) -> Markup { html! { p id=[self.id()] class=[self.classes()] { (*self.html()) } } diff --git a/pagetop/src/base/theme/aliner.rs b/pagetop/src/base/theme/aliner.rs index d27c4632..ae6c7475 100644 --- a/pagetop/src/base/theme/aliner.rs +++ b/pagetop/src/base/theme/aliner.rs @@ -16,7 +16,7 @@ impl ThemeTrait for Aliner { } fn before_render_page(&self, page: &mut Page) { - page.assets() + page.context() .with_favicon( Favicon::new() .with_icon("/theme/favicon.png") diff --git a/pagetop/src/base/theme/bootsier.rs b/pagetop/src/base/theme/bootsier.rs index 5471b5cf..494bda17 100644 --- a/pagetop/src/base/theme/bootsier.rs +++ b/pagetop/src/base/theme/bootsier.rs @@ -18,7 +18,7 @@ impl ThemeTrait for Bootsier { } fn before_render_page(&self, page: &mut Page) { - page.assets() + page.context() .with_favicon( Favicon::new() .with_icon("/theme/favicon.png") diff --git a/pagetop/src/base/theme/bulmix.rs b/pagetop/src/base/theme/bulmix.rs index b4a360fb..e6041798 100644 --- a/pagetop/src/base/theme/bulmix.rs +++ b/pagetop/src/base/theme/bulmix.rs @@ -16,7 +16,7 @@ impl ThemeTrait for Bulmix { } fn before_render_page(&self, page: &mut Page) { - page.assets() + page.context() .with_favicon( Favicon::new() .with_icon("/theme/favicon.png") @@ -33,7 +33,7 @@ impl ThemeTrait for Bulmix { fn before_render_component( &self, component: &mut dyn ComponentTrait, - _assets: &mut Assets + _context: &mut Context ) { match component.handler() { HEADING_COMPONENT => { diff --git a/pagetop/src/core/component.rs b/pagetop/src/core/component.rs index c0c78a57..f11f6b1b 100644 --- a/pagetop/src/core/component.rs +++ b/pagetop/src/core/component.rs @@ -4,9 +4,9 @@ pub use hook::{ BeforeRenderComponentHook, }; -mod assets; -pub use assets::{ - Assets, +mod context; +pub use context::{ + Context, Favicon, JavaScript, JSMode, StyleSheet, diff --git a/pagetop/src/core/component/assets.rs b/pagetop/src/core/component/assets.rs deleted file mode 100644 index 563e33c9..00000000 --- a/pagetop/src/core/component/assets.rs +++ /dev/null @@ -1,302 +0,0 @@ -use crate::{Lazy, base, concat_string, util}; -use crate::config::SETTINGS; -use crate::html::{Markup, PreEscaped, html}; -use crate::core::theme::*; - -static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - match all::theme_by_single_name(&SETTINGS.app.theme) { - Some(theme) => theme, - None => &base::theme::bootsier::Bootsier, - } -}); - -// Favicon. - -pub struct Favicon(Vec); - -impl Favicon { - pub fn new() -> Self { - Favicon(Vec::new()) - } - - pub fn with_icon(self, image: &str) -> Self { - self.add_item("icon", image, "", "") - } - - pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { - self.add_item("icon", image, sizes, "") - } - - pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { - self.add_item("apple-touch-icon", image, sizes, "") - } - - pub fn with_mask_icon(self, image: &str, color: &str) -> Self { - self.add_item("mask-icon", image, "", color) - } - - pub fn with_manifest(self, file: &str) -> Self { - self.add_item("manifest", file, "", "") - } - - pub fn with_theme_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_image(mut self, image: &str) -> Self { - self.0.push(format!( - "", image - )); - self - } - - fn add_item( - mut self, - rel : &str, - source: &str, - sizes : &str, - color : &str - ) -> Self { - let mut link: String = format!(" format!("{} type=\"image/gif\"", link), - ".ico" => format!("{} type=\"image/x-icon\"", link), - ".jpg" => format!("{} type=\"image/jpg\"", link), - ".png" => format!("{} type=\"image/png\"", link), - ".svg" => format!("{} type=\"image/svg+xml\"", link), - _ => link - }; - } - if !sizes.is_empty() { - link = format!("{} sizes=\"{}\"", link, sizes); - } - if !color.is_empty() { - link = format!("{} color=\"{}\"", link, color); - } - self.0.push(format!("{} href=\"{}\">", link, source)); - self - } - - fn render(&self) -> Markup { - html! { - @for item in &self.0 { - (PreEscaped(item)) - } - } - } -} - -// JavaScript. - -#[derive(PartialEq)] -pub enum JSMode { Async, Defer, Normal } - -pub struct JavaScript { - source: &'static str, - weight: isize, - mode : JSMode, -} -impl JavaScript { - pub fn source(s: &'static str) -> Self { - JavaScript { - source: s, - weight: 0, - mode : JSMode::Defer, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn with_mode(mut self, mode: JSMode) -> Self { - self.mode = mode; - self - } - - pub fn weight(self) -> isize { - self.weight - } - - fn render(&self) -> Markup { - html! { - script type="text/javascript" - src=(self.source) - async[self.mode == JSMode::Async] - defer[self.mode == JSMode::Defer] - {}; - } - } -} - -// StyleSheet. - -pub struct StyleSheet { - source: &'static str, - weight: isize, -} -impl StyleSheet { - pub fn source(s: &'static str) -> Self { - StyleSheet { - source: s, - weight: 0, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn weight(self) -> isize { - self.weight - } - - fn render(&self) -> Markup { - html! { - link rel="stylesheet" href=(self.source); - } - } -} - -// Page assets. - -pub struct Assets { - theme : &'static dyn ThemeTrait, - favicon : Option, - metadata : Vec<(String, String)>, - stylesheets: Vec, - javascripts: Vec, - with_jquery: bool, - id_counter : usize, -} - -impl Assets { - pub fn new() -> Self { - Assets { - theme : *DEFAULT_THEME, - favicon : None, - metadata : Vec::new(), - stylesheets: Vec::new(), - javascripts: Vec::new(), - with_jquery: false, - id_counter : 0, - } - } - - pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); - self - } - - pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self { - self.favicon = Some(favicon); - self - } - - pub fn add_metadata(&mut self, name: String, content: String) -> &mut Self { - self.metadata.push((name, content)); - self - } - - pub fn add_stylesheet(&mut self, css: StyleSheet) -> &mut Self { - match self.stylesheets.iter().position(|x| x.source == css.source) { - Some(index) => if self.stylesheets[index].weight > css.weight { - self.stylesheets.remove(index); - self.stylesheets.push(css); - }, - _ => self.stylesheets.push(css) - } - self - } - - pub fn add_javascript(&mut self, js: JavaScript) -> &mut Self { - match self.javascripts.iter().position(|x| x.source == js.source) { - Some(index) => if self.javascripts[index].weight > js.weight { - self.javascripts.remove(index); - self.javascripts.push(js); - }, - _ => self.javascripts.push(js) - } - self - } - - pub fn add_jquery(&mut self) -> &mut Self { - if !self.with_jquery { - self.add_javascript( - JavaScript::source( - "/theme/js/jquery.min.js?ver=3.6.0" - ) - .with_weight(isize::MIN) - .with_mode(JSMode::Normal) - ); - self.with_jquery = true; - } - self - } - - /// Assets GETTERS. - - pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait { - self.theme - } - - /// Assets RENDER. - - pub fn render(&mut self) -> Markup { - let ordered_css = &mut self.stylesheets; - ordered_css.sort_by_key(|o| o.weight); - - let ordered_js = &mut self.javascripts; - ordered_js.sort_by_key(|o| o.weight); - - html! { - @match &self.favicon { - Some(favicon) => (favicon.render()), - None => "", - } - @for (name, content) in &self.metadata { - meta name=(name) content=(content) {} - } - @for css in ordered_css { - (css.render()) - } - @for js in ordered_js { - (js.render()) - } - } - } - - // Assets EXTRAS. - - pub fn required_id(&mut self, id: &Option) -> String { - match id { - Some(id) => id.to_string(), - None => { - let prefix = util::single_type_name::() - .trim() - .replace(" ", "_") - .to_lowercase(); - let prefix = if prefix.is_empty() { - "prefix".to_owned() - } else { - prefix - }; - self.id_counter += 1; - concat_string!(prefix, "-", self.id_counter.to_string()) - } - } - } -} diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs new file mode 100644 index 00000000..3aeab266 --- /dev/null +++ b/pagetop/src/core/component/context.rs @@ -0,0 +1,148 @@ +use crate::{Lazy, base, concat_string, util}; +use crate::config::SETTINGS; +use crate::html::{Markup, html}; +use crate::core::theme::*; + +mod favicon; +pub use favicon::Favicon; + +mod javascript; +pub use javascript::{JavaScript, JSMode}; + +mod stylesheet; +pub use stylesheet::StyleSheet; + +static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { + match all::theme_by_single_name(&SETTINGS.app.theme) { + Some(theme) => theme, + None => &base::theme::bootsier::Bootsier, + } +}); + +pub struct Context { + theme : &'static dyn ThemeTrait, + favicon : Option, + metadata : Vec<(String, String)>, + stylesheets: Vec, + javascripts: Vec, + with_jquery: bool, + id_counter : usize, +} + +impl Context { + pub fn new() -> Self { + Context { + theme : *DEFAULT_THEME, + favicon : None, + metadata : Vec::new(), + stylesheets: Vec::new(), + javascripts: Vec::new(), + with_jquery: false, + id_counter : 0, + } + } + + pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { + self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); + self + } + + pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self { + self.favicon = Some(favicon); + self + } + + pub fn add_metadata(&mut self, name: String, content: String) -> &mut Self { + self.metadata.push((name, content)); + self + } + + pub fn add_stylesheet(&mut self, css: StyleSheet) -> &mut Self { + match self.stylesheets.iter().position(|x| x.source == css.source) { + Some(index) => if self.stylesheets[index].weight > css.weight { + self.stylesheets.remove(index); + self.stylesheets.push(css); + }, + _ => self.stylesheets.push(css) + } + self + } + + pub fn add_javascript(&mut self, js: JavaScript) -> &mut Self { + match self.javascripts.iter().position(|x| x.source == js.source) { + Some(index) => if self.javascripts[index].weight > js.weight { + self.javascripts.remove(index); + self.javascripts.push(js); + }, + _ => self.javascripts.push(js) + } + self + } + + pub fn add_jquery(&mut self) -> &mut Self { + if !self.with_jquery { + self.add_javascript( + JavaScript::source( + "/theme/js/jquery.min.js?ver=3.6.0" + ) + .with_weight(isize::MIN) + .with_mode(JSMode::Normal) + ); + self.with_jquery = true; + } + self + } + + /// Context GETTERS. + + pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait { + self.theme + } + + /// Context RENDER. + + pub fn render(&mut self) -> Markup { + let ordered_css = &mut self.stylesheets; + ordered_css.sort_by_key(|o| o.weight); + + let ordered_js = &mut self.javascripts; + ordered_js.sort_by_key(|o| o.weight); + + html! { + @match &self.favicon { + Some(favicon) => (favicon.render()), + None => "", + } + @for (name, content) in &self.metadata { + meta name=(name) content=(content) {} + } + @for css in ordered_css { + (css.render()) + } + @for js in ordered_js { + (js.render()) + } + } + } + + // Context EXTRAS. + + pub fn required_id(&mut self, id: &Option) -> String { + match id { + Some(id) => id.to_string(), + None => { + let prefix = util::single_type_name::() + .trim() + .replace(" ", "_") + .to_lowercase(); + let prefix = if prefix.is_empty() { + "prefix".to_owned() + } else { + prefix + }; + self.id_counter += 1; + concat_string!(prefix, "-", self.id_counter.to_string()) + } + } + } +} diff --git a/pagetop/src/core/component/context/favicon.rs b/pagetop/src/core/component/context/favicon.rs new file mode 100644 index 00000000..1788540e --- /dev/null +++ b/pagetop/src/core/component/context/favicon.rs @@ -0,0 +1,86 @@ +use crate::html::{Markup, PreEscaped, html}; + +pub struct Favicon(Vec); + +impl Favicon { + pub fn new() -> Self { + Favicon(Vec::new()) + } + + pub fn with_icon(self, image: &str) -> Self { + self.add_item("icon", image, "", "") + } + + pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { + self.add_item("icon", image, sizes, "") + } + + pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { + self.add_item("apple-touch-icon", image, sizes, "") + } + + pub fn with_mask_icon(self, image: &str, color: &str) -> Self { + self.add_item("mask-icon", image, "", color) + } + + pub fn with_manifest(self, file: &str) -> Self { + self.add_item("manifest", file, "", "") + } + + pub fn with_theme_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_image(mut self, image: &str) -> Self { + self.0.push(format!( + "", image + )); + self + } + + fn add_item( + mut self, + rel : &str, + source: &str, + sizes : &str, + color : &str + ) -> Self { + let mut link: String = format!(" format!("{} type=\"image/gif\"", link), + ".ico" => format!("{} type=\"image/x-icon\"", link), + ".jpg" => format!("{} type=\"image/jpg\"", link), + ".png" => format!("{} type=\"image/png\"", link), + ".svg" => format!("{} type=\"image/svg+xml\"", link), + _ => link + }; + } + if !sizes.is_empty() { + link = format!("{} sizes=\"{}\"", link, sizes); + } + if !color.is_empty() { + link = format!("{} color=\"{}\"", link, color); + } + self.0.push(format!("{} href=\"{}\">", link, source)); + self + } + + pub(super) fn render(&self) -> Markup { + html! { + @for item in &self.0 { + (PreEscaped(item)) + } + } + } +} diff --git a/pagetop/src/core/component/context/javascript.rs b/pagetop/src/core/component/context/javascript.rs new file mode 100644 index 00000000..2f2d725b --- /dev/null +++ b/pagetop/src/core/component/context/javascript.rs @@ -0,0 +1,43 @@ +use crate::html::{Markup, html}; + +#[derive(PartialEq)] +pub enum JSMode { Async, Defer, Normal } + +pub struct JavaScript { + pub(super) source: &'static str, + pub(super) weight: isize, + pub(super) mode : JSMode, +} +impl JavaScript { + pub fn source(s: &'static str) -> Self { + JavaScript { + source: s, + weight: 0, + mode : JSMode::Defer, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn with_mode(mut self, mode: JSMode) -> Self { + self.mode = mode; + self + } + + pub fn weight(self) -> isize { + self.weight + } + + pub(super) fn render(&self) -> Markup { + html! { + script type="text/javascript" + src=(self.source) + async[self.mode == JSMode::Async] + defer[self.mode == JSMode::Defer] + {}; + } + } +} diff --git a/pagetop/src/core/component/context/stylesheet.rs b/pagetop/src/core/component/context/stylesheet.rs new file mode 100644 index 00000000..f7803938 --- /dev/null +++ b/pagetop/src/core/component/context/stylesheet.rs @@ -0,0 +1,29 @@ +use crate::html::{Markup, html}; + +pub struct StyleSheet { + pub(super) source: &'static str, + pub(super) weight: isize, +} +impl StyleSheet { + pub fn source(s: &'static str) -> Self { + StyleSheet { + source: s, + weight: 0, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn weight(self) -> isize { + self.weight + } + + pub(super) fn render(&self) -> Markup { + html! { + link rel="stylesheet" href=(self.source); + } + } +} diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index 45fa3e91..ce57b240 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -1,8 +1,7 @@ use crate::util; use crate::html::{Markup, html}; use crate::core::hook::{hook_ref, run_hooks}; -use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook}; -use super::Assets; +use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook, Context}; pub use std::any::Any as AnyComponent; @@ -28,11 +27,11 @@ pub trait ComponentTrait: AnyComponent + Send + Sync { } #[allow(unused_variables)] - fn before_render(&mut self, assets: &mut Assets) { + fn before_render(&mut self, context: &mut Context) { } #[allow(unused_variables)] - fn default_render(&self, assets: &mut Assets) -> Markup { + fn default_render(&self, context: &mut Context) -> Markup { html! {} } @@ -49,24 +48,24 @@ pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { component.as_mut_any().downcast_mut::().unwrap() } -pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) -> Markup { +pub fn render_component(component: &mut dyn ComponentTrait, context: &mut Context) -> Markup { // Acciones del componente antes de renderizar. - component.before_render(assets); + component.before_render(context); // Acciones de los módulos antes de renderizar el componente. run_hooks( BEFORE_RENDER_COMPONENT_HOOK, - |a| hook_ref::(&**a).run(component, assets) + |a| hook_ref::(&**a).run(component, context) ); // Acciones del tema antes de renderizar el componente. - assets.theme().before_render_component(component, assets); + context.theme().before_render_component(component, context); match component.is_renderable() { true => { - match assets.theme().render_component(component, assets) { + match context.theme().render_component(component, context) { Some(html) => html, - None => component.default_render(assets) + None => component.default_render(context) } }, false => html! {} diff --git a/pagetop/src/core/component/holder.rs b/pagetop/src/core/component/holder.rs index 51b67736..b19eb7f2 100644 --- a/pagetop/src/core/component/holder.rs +++ b/pagetop/src/core/component/holder.rs @@ -1,5 +1,5 @@ use crate::html::{Markup, html}; -use super::{Assets, ComponentTrait}; +use super::{Context, ComponentTrait}; use std::sync::{Arc, RwLock}; @@ -21,12 +21,12 @@ impl ComponentsHolder { self.0.push(Arc::new(RwLock::new(component))); } - pub fn render(&self, assets: &mut Assets) -> Markup { + pub fn render(&self, context: &mut Context) -> Markup { let mut components = self.0.clone(); components.sort_by_key(|c| c.read().unwrap().weight()); html! { @for c in components.iter() { - (super::render_component(&mut *c.write().unwrap(), assets)) + (super::render_component(&mut *c.write().unwrap(), context)) } } } diff --git a/pagetop/src/core/component/hook.rs b/pagetop/src/core/component/hook.rs index f52d755b..e29ac1eb 100644 --- a/pagetop/src/core/component/hook.rs +++ b/pagetop/src/core/component/hook.rs @@ -1,10 +1,10 @@ use crate::core::hook::{HookTrait, AnyHook}; -use super::{Assets, ComponentTrait}; +use super::{ComponentTrait, Context}; pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::hook::before_render_component"; pub struct BeforeRenderComponentHook { - hook: Option, + hook: Option, weight: isize, } @@ -30,7 +30,7 @@ impl HookTrait for BeforeRenderComponentHook { } impl BeforeRenderComponentHook { - pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { + pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Context)) -> Self { self.hook = Some(hook); self } @@ -40,9 +40,9 @@ impl BeforeRenderComponentHook { self } - pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) { + pub fn run(&self, component: &mut dyn ComponentTrait, context: &mut Context) { if let Some(hook) = self.hook { - hook(component, assets) + hook(component, context) } } } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 74457e19..205ea6cd 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -2,7 +2,7 @@ use crate::{concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::core::app; -use crate::core::component::{Assets, ComponentTrait, Favicon}; +use crate::core::component::{ComponentTrait, Context, Favicon}; use crate::response::page::Page; use crate::base::component::Chunck; @@ -28,7 +28,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { #[allow(unused_variables)] fn before_render_page(&self, page: &mut Page) { - page.assets() + page.context() .with_favicon( Favicon::new() .with_icon("/theme/favicon.png") @@ -56,7 +56,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { meta http-equiv="X-UA-Compatible" content="IE=edge"; meta name="viewport" content=(viewport); - (page.assets().render()) + (page.context().render()) } } } @@ -86,7 +86,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn before_render_component( &self, component: &mut dyn ComponentTrait, - assets: &mut Assets + context: &mut Context ) { /* Cómo usarlo: @@ -105,7 +105,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn render_component( &self, component: &dyn ComponentTrait, - assets: &mut Assets + context: &mut Context ) -> Option { None /* diff --git a/pagetop/src/response/page/definition.rs b/pagetop/src/response/page/definition.rs index 6febf1ac..f57de4ee 100644 --- a/pagetop/src/response/page/definition.rs +++ b/pagetop/src/response/page/definition.rs @@ -42,7 +42,7 @@ pub struct Page<'a> { direction : OptAttr, title : OptAttr, description : OptAttr, - assets : Assets, + context : Context, regions : HashMap<&'a str, ComponentsHolder>, body_classes: Classes, template : String, @@ -62,7 +62,7 @@ impl<'a> Page<'a> { }, title : OptAttr::new(), description : OptAttr::new(), - assets : Assets::new(), + context : Context::new(), regions : common_components(), body_classes: Classes::new_with_default("body"), template : "default".to_owned(), @@ -136,8 +136,8 @@ impl<'a> Page<'a> { self.description.option() } - pub fn assets(&mut self) -> &mut Assets { - &mut self.assets + pub fn context(&mut self) -> &mut Context { + &mut self.context } pub fn body_classes(&self) -> &Option { @@ -158,13 +158,13 @@ impl<'a> Page<'a> { ); // Acciones del tema antes de renderizar la página. - self.assets.theme().before_render_page(self); + self.context.theme().before_render_page(self); // Primero, renderizar el cuerpo. - let body = self.assets.theme().render_page_body(self); + let body = self.context.theme().render_page_body(self); // Luego, renderizar la cabecera. - let head = self.assets.theme().render_page_head(self); + let head = self.context.theme().render_page_head(self); // Finalmente, renderizar la página. return Ok(html! { @@ -178,7 +178,7 @@ impl<'a> Page<'a> { pub fn render_region(&mut self, region: &str) -> Markup { match self.regions.get_mut(region) { - Some(components) => components.render(&mut self.assets), + Some(components) => components.render(&mut self.context), None => html! {} } } @@ -186,7 +186,7 @@ impl<'a> Page<'a> { // Page EXTRAS. pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.assets.using_theme(theme_name); + self.context.using_theme(theme_name); self } } From 96cbbb0c3c7b87266e1f38f1c12a807d87c638cb Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 20:12:59 +0200 Subject: [PATCH 65/80] Actualiza nomenclatura de tipos --- pagetop/src/base/component/anchor.rs | 2 +- pagetop/src/base/component/block.rs | 8 ++++---- pagetop/src/base/component/chunck.rs | 2 +- pagetop/src/base/component/container.rs | 8 ++++---- pagetop/src/base/component/form/button.rs | 2 +- pagetop/src/base/component/form/date.rs | 2 +- pagetop/src/base/component/form/form.rs | 8 ++++---- pagetop/src/base/component/form/hidden.rs | 2 +- pagetop/src/base/component/form/input.rs | 4 ++-- pagetop/src/base/component/grid/column.rs | 8 ++++---- pagetop/src/base/component/grid/row.rs | 8 ++++---- pagetop/src/base/component/heading.rs | 2 +- pagetop/src/base/component/image.rs | 2 +- pagetop/src/base/component/menu.rs | 10 +++++----- pagetop/src/base/component/paragraph.rs | 2 +- pagetop/src/base/theme/bulmix.rs | 2 +- pagetop/src/core/component.rs | 6 +++--- pagetop/src/core/component/all.rs | 8 ++++---- .../src/core/component/{holder.rs => bundle.rs} | 12 ++++++------ pagetop/src/core/component/context.rs | 16 ++++++++-------- pagetop/src/core/component/definition.rs | 8 ++++---- pagetop/src/core/component/hook.rs | 8 ++++---- pagetop/src/core/theme/definition.rs | 6 +++--- pagetop/src/response/page/definition.rs | 10 +++++----- 24 files changed, 73 insertions(+), 73 deletions(-) rename pagetop/src/core/component/{holder.rs => bundle.rs} (69%) diff --git a/pagetop/src/base/component/anchor.rs b/pagetop/src/base/component/anchor.rs index 1d0ce8a1..0c100f04 100644 --- a/pagetop/src/base/component/anchor.rs +++ b/pagetop/src/base/component/anchor.rs @@ -55,7 +55,7 @@ impl ComponentTrait for Anchor { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { let target = match &self.target() { AnchorTarget::Blank => Some("_blank"), AnchorTarget::Context(name) => Some(name.as_str()), diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index a37bc2ed..c3581654 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -5,7 +5,7 @@ pub const BLOCK_COMPONENT: &str = "pagetop::component::block"; pub struct Block { renderable: fn() -> bool, weight : isize, - components: ComponentsHolder, + components: ComponentsBundle, title : OptAttr, id : OptIden, classes : Classes, @@ -17,7 +17,7 @@ impl ComponentTrait for Block { Block { renderable: render_always, weight : 0, - components: ComponentsHolder::new(), + components: ComponentsBundle::new(), title : OptAttr::new(), id : OptIden::new(), classes : Classes::new_with_default("block"), @@ -37,7 +37,7 @@ impl ComponentTrait for Block { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { let id = context.required_id::(self.id()); html! { div id=(id) class=[self.classes()] { @@ -70,7 +70,7 @@ impl Block { self } - pub fn components(&self) -> &ComponentsHolder { + pub fn components(&self) -> &ComponentsBundle { &self.components } diff --git a/pagetop/src/base/component/chunck.rs b/pagetop/src/base/component/chunck.rs index fdbfe9ee..1832a455 100644 --- a/pagetop/src/base/component/chunck.rs +++ b/pagetop/src/base/component/chunck.rs @@ -31,7 +31,7 @@ impl ComponentTrait for Chunck { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { html! { (*self.html()) } } diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index 7be54148..f7e59740 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -7,7 +7,7 @@ pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { renderable : fn() -> bool, weight : isize, - components : ComponentsHolder, + components : ComponentsBundle, container : ContainerType, id : OptIden, classes : Classes, @@ -20,7 +20,7 @@ impl ComponentTrait for Container { Container { renderable : render_always, weight : 0, - components : ComponentsHolder::new(), + components : ComponentsBundle::new(), container : ContainerType::Wrapper, id : OptIden::new(), classes : Classes::new_with_default("container"), @@ -41,7 +41,7 @@ impl ComponentTrait for Container { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { match self.container_type() { ContainerType::Header => html! { header id=[self.id()] class=[self.classes()] { @@ -120,7 +120,7 @@ impl Container { self } - pub fn components(&self) -> &ComponentsHolder { + pub fn components(&self) -> &ComponentsBundle { &self.components } diff --git a/pagetop/src/base/component/form/button.rs b/pagetop/src/base/component/form/button.rs index ad042b60..fc3e82b3 100644 --- a/pagetop/src/base/component/form/button.rs +++ b/pagetop/src/base/component/form/button.rs @@ -44,7 +44,7 @@ impl ComponentTrait for Button { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { let button_type = match self.button_type() { ButtonType::Button => "button", ButtonType::Reset => "reset", diff --git a/pagetop/src/base/component/form/date.rs b/pagetop/src/base/component/form/date.rs index 763a474a..19ba44a9 100644 --- a/pagetop/src/base/component/form/date.rs +++ b/pagetop/src/base/component/form/date.rs @@ -52,7 +52,7 @@ impl ComponentTrait for Date { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("edit-", name)), None => None, diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index 688eeeed..72c3bbcd 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -7,7 +7,7 @@ pub enum FormMethod {Get, Post} pub struct Form { renderable: fn() -> bool, weight : isize, - elements : ComponentsHolder, + elements : ComponentsBundle, action : OptAttr, charset : OptAttr, method : FormMethod, @@ -21,7 +21,7 @@ impl ComponentTrait for Form { Form { renderable: render_always, weight : 0, - elements : ComponentsHolder::new(), + elements : ComponentsBundle::new(), action : OptAttr::new(), charset : OptAttr::new_with_value("UTF-8"), method : FormMethod::Post, @@ -43,7 +43,7 @@ impl ComponentTrait for Form { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { let method = match self.method() { FormMethod::Get => None, FormMethod::Post => Some("post".to_owned()) @@ -79,7 +79,7 @@ impl Form { self } - pub fn elements(&self) -> &ComponentsHolder { + pub fn elements(&self) -> &ComponentsBundle { &self.elements } diff --git a/pagetop/src/base/component/form/hidden.rs b/pagetop/src/base/component/form/hidden.rs index 91a2986f..83bca41b 100644 --- a/pagetop/src/base/component/form/hidden.rs +++ b/pagetop/src/base/component/form/hidden.rs @@ -25,7 +25,7 @@ impl ComponentTrait for Hidden { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { let id = match self.name() { Some(name) => Some(concat_string!("value-", name)), _ => None diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 806be50a..c96197e8 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -62,14 +62,14 @@ impl ComponentTrait for Input { self.weight } - fn before_render(&mut self, _: &mut Context) { + fn before_render(&mut self, _: &mut InContext) { if let Some(name) = self.name() { let class = concat_string!("form-item-", name); self.alter_classes(class.as_str(), ClassesOp::AddFirst); } } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { let type_input = match self.input_type() { InputType::Email => "email", InputType::Password => "password", diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index b06faea2..4cf0f48e 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -5,7 +5,7 @@ pub const COLUMN_COMPONENT: &str = "pagetop::component::grid::column"; pub struct Column { renderable: fn() -> bool, weight : isize, - components: ComponentsHolder, + components: ComponentsBundle, id : OptIden, classes : Classes, template : String, @@ -16,7 +16,7 @@ impl ComponentTrait for Column { Column { renderable: render_always, weight : 0, - components: ComponentsHolder::new(), + components: ComponentsBundle::new(), id : OptIden::new(), classes : Classes::new_with_default("col"), template : "default".to_owned(), @@ -35,7 +35,7 @@ impl ComponentTrait for Column { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { html! { div id=[self.id()] class=[self.classes()] { (self.components().render(context)) @@ -61,7 +61,7 @@ impl Column { self } - pub fn components(&self) -> &ComponentsHolder { + pub fn components(&self) -> &ComponentsBundle { &self.components } diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 0ffe3f08..57f44568 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -5,7 +5,7 @@ pub const ROW_COMPONENT: &str = "pagetop::component::grid::row"; pub struct Row { renderable: fn() -> bool, weight : isize, - columns : ComponentsHolder, + columns : ComponentsBundle, id : OptIden, classes : Classes, template : String, @@ -16,7 +16,7 @@ impl ComponentTrait for Row { Row { renderable: render_always, weight : 0, - columns : ComponentsHolder::new(), + columns : ComponentsBundle::new(), id : OptIden::new(), classes : Classes::new_with_default("row"), template : "default".to_owned(), @@ -35,7 +35,7 @@ impl ComponentTrait for Row { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { html! { div id=[self.id()] class=[self.classes()] { (self.columns().render(context)) @@ -61,7 +61,7 @@ impl Row { self } - pub fn columns(&self) -> &ComponentsHolder { + pub fn columns(&self) -> &ComponentsBundle { &self.columns } diff --git a/pagetop/src/base/component/heading.rs b/pagetop/src/base/component/heading.rs index eada3ea5..4248fb03 100644 --- a/pagetop/src/base/component/heading.rs +++ b/pagetop/src/base/component/heading.rs @@ -50,7 +50,7 @@ impl ComponentTrait for Heading { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { html! { @match &self.heading() { HeadingType::H1 => h1 id=[self.id()] class=[self.classes()] { (*self.html()) }, HeadingType::H2 => h2 id=[self.id()] class=[self.classes()] { (*self.html()) }, diff --git a/pagetop/src/base/component/image.rs b/pagetop/src/base/component/image.rs index 5a3f16c6..3d3a361e 100644 --- a/pagetop/src/base/component/image.rs +++ b/pagetop/src/base/component/image.rs @@ -35,7 +35,7 @@ impl ComponentTrait for Image { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { html! { img src=[self.source()] diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index c4a97a05..ef7668aa 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -42,7 +42,7 @@ impl ComponentTrait for MenuItem { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { match self.item_type() { MenuItemType::Label(label) => html! { li class="label" { a href="#" { (label) } } @@ -176,7 +176,7 @@ impl MenuItem { pub struct Menu { renderable: fn() -> bool, weight : isize, - items : ComponentsHolder, + items : ComponentsBundle, id : OptIden, classes : Classes, template : String, @@ -187,7 +187,7 @@ impl ComponentTrait for Menu { Menu { renderable: render_always, weight : 0, - items : ComponentsHolder::new(), + items : ComponentsBundle::new(), id : OptIden::new(), classes : Classes::new_with_default("sm sm-clean"), template : "default".to_owned(), @@ -206,7 +206,7 @@ impl ComponentTrait for Menu { self.weight } - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { context .add_stylesheet(StyleSheet::source( "/theme/menu/css/menu.css?ver=1.1.1" @@ -251,7 +251,7 @@ impl Menu { self } - pub fn items(&self) -> &ComponentsHolder { + pub fn items(&self) -> &ComponentsBundle { &self.items } diff --git a/pagetop/src/base/component/paragraph.rs b/pagetop/src/base/component/paragraph.rs index d8e1ac4b..c0d7d93c 100644 --- a/pagetop/src/base/component/paragraph.rs +++ b/pagetop/src/base/component/paragraph.rs @@ -46,7 +46,7 @@ impl ComponentTrait for Paragraph { self.weight } - fn default_render(&self, _: &mut Context) -> Markup { + fn default_render(&self, _: &mut InContext) -> Markup { html! { p id=[self.id()] class=[self.classes()] { (*self.html()) } } diff --git a/pagetop/src/base/theme/bulmix.rs b/pagetop/src/base/theme/bulmix.rs index e6041798..f099d880 100644 --- a/pagetop/src/base/theme/bulmix.rs +++ b/pagetop/src/base/theme/bulmix.rs @@ -33,7 +33,7 @@ impl ThemeTrait for Bulmix { fn before_render_component( &self, component: &mut dyn ComponentTrait, - _context: &mut Context + _context: &mut InContext ) { match component.handler() { HEADING_COMPONENT => { diff --git a/pagetop/src/core/component.rs b/pagetop/src/core/component.rs index f11f6b1b..038ee93d 100644 --- a/pagetop/src/core/component.rs +++ b/pagetop/src/core/component.rs @@ -5,8 +5,8 @@ pub use hook::{ }; mod context; +pub use context::InContext; pub use context::{ - Context, Favicon, JavaScript, JSMode, StyleSheet, @@ -21,8 +21,8 @@ pub use definition::{ }; use definition::render_component; -mod holder; -pub use holder::ComponentsHolder; +mod bundle; +pub use bundle::ComponentsBundle; mod all; pub use all::add_component_to; diff --git a/pagetop/src/core/component/all.rs b/pagetop/src/core/component/all.rs index 82573f59..a8567794 100644 --- a/pagetop/src/core/component/all.rs +++ b/pagetop/src/core/component/all.rs @@ -1,10 +1,10 @@ use crate::Lazy; -use super::{ComponentsHolder, ComponentTrait}; +use super::{ComponentsBundle, ComponentTrait}; use std::sync::RwLock; use std::collections::HashMap; -static COMPONENTS: Lazy>> = Lazy::new(|| { +static COMPONENTS: Lazy>> = Lazy::new(|| { RwLock::new(HashMap::new()) }); @@ -13,10 +13,10 @@ pub fn add_component_to(region: &'static str, component: impl ComponentTrait) { if let Some(regions) = hmap.get_mut(region) { regions.add(component); } else { - hmap.insert(region, ComponentsHolder::new_with(component)); + hmap.insert(region, ComponentsBundle::new_with(component)); } } -pub fn common_components() -> HashMap<&'static str, ComponentsHolder> { +pub fn common_components() -> HashMap<&'static str, ComponentsBundle> { COMPONENTS.read().unwrap().clone() } diff --git a/pagetop/src/core/component/holder.rs b/pagetop/src/core/component/bundle.rs similarity index 69% rename from pagetop/src/core/component/holder.rs rename to pagetop/src/core/component/bundle.rs index b19eb7f2..0477a4fd 100644 --- a/pagetop/src/core/component/holder.rs +++ b/pagetop/src/core/component/bundle.rs @@ -1,18 +1,18 @@ use crate::html::{Markup, html}; -use super::{Context, ComponentTrait}; +use super::{InContext, ComponentTrait}; use std::sync::{Arc, RwLock}; #[derive(Clone)] -pub struct ComponentsHolder(Vec>>); +pub struct ComponentsBundle(Vec>>); -impl ComponentsHolder { +impl ComponentsBundle { pub fn new() -> Self { - ComponentsHolder(Vec::new()) + ComponentsBundle(Vec::new()) } pub fn new_with(component: impl ComponentTrait) -> Self { - let mut container = ComponentsHolder::new(); + let mut container = ComponentsBundle::new(); container.add(component); container } @@ -21,7 +21,7 @@ impl ComponentsHolder { self.0.push(Arc::new(RwLock::new(component))); } - pub fn render(&self, context: &mut Context) -> Markup { + pub fn render(&self, context: &mut InContext) -> Markup { let mut components = self.0.clone(); components.sort_by_key(|c| c.read().unwrap().weight()); html! { diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs index 3aeab266..a5c7a43a 100644 --- a/pagetop/src/core/component/context.rs +++ b/pagetop/src/core/component/context.rs @@ -19,7 +19,7 @@ static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { } }); -pub struct Context { +pub struct InContext { theme : &'static dyn ThemeTrait, favicon : Option, metadata : Vec<(String, String)>, @@ -29,9 +29,9 @@ pub struct Context { id_counter : usize, } -impl Context { +impl InContext { pub fn new() -> Self { - Context { + InContext { theme : *DEFAULT_THEME, favicon : None, metadata : Vec::new(), @@ -93,20 +93,20 @@ impl Context { self } - /// Context GETTERS. + /// InContext GETTERS. pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait { self.theme } - /// Context RENDER. + /// InContext RENDER. pub fn render(&mut self) -> Markup { let ordered_css = &mut self.stylesheets; - ordered_css.sort_by_key(|o| o.weight); + ordered_css.sort_by_key(|css| css.weight); let ordered_js = &mut self.javascripts; - ordered_js.sort_by_key(|o| o.weight); + ordered_js.sort_by_key(|js| js.weight); html! { @match &self.favicon { @@ -125,7 +125,7 @@ impl Context { } } - // Context EXTRAS. + // InContext EXTRAS. pub fn required_id(&mut self, id: &Option) -> String { match id { diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index ce57b240..96950798 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -1,7 +1,7 @@ use crate::util; use crate::html::{Markup, html}; use crate::core::hook::{hook_ref, run_hooks}; -use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook, Context}; +use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook, InContext}; pub use std::any::Any as AnyComponent; @@ -27,11 +27,11 @@ pub trait ComponentTrait: AnyComponent + Send + Sync { } #[allow(unused_variables)] - fn before_render(&mut self, context: &mut Context) { + fn before_render(&mut self, context: &mut InContext) { } #[allow(unused_variables)] - fn default_render(&self, context: &mut Context) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { html! {} } @@ -48,7 +48,7 @@ pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { component.as_mut_any().downcast_mut::().unwrap() } -pub fn render_component(component: &mut dyn ComponentTrait, context: &mut Context) -> Markup { +pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InContext) -> Markup { // Acciones del componente antes de renderizar. component.before_render(context); diff --git a/pagetop/src/core/component/hook.rs b/pagetop/src/core/component/hook.rs index e29ac1eb..82d1ba01 100644 --- a/pagetop/src/core/component/hook.rs +++ b/pagetop/src/core/component/hook.rs @@ -1,10 +1,10 @@ use crate::core::hook::{HookTrait, AnyHook}; -use super::{ComponentTrait, Context}; +use super::{ComponentTrait, InContext}; pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::hook::before_render_component"; pub struct BeforeRenderComponentHook { - hook: Option, + hook: Option, weight: isize, } @@ -30,7 +30,7 @@ impl HookTrait for BeforeRenderComponentHook { } impl BeforeRenderComponentHook { - pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Context)) -> Self { + pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut InContext)) -> Self { self.hook = Some(hook); self } @@ -40,7 +40,7 @@ impl BeforeRenderComponentHook { self } - pub fn run(&self, component: &mut dyn ComponentTrait, context: &mut Context) { + pub fn run(&self, component: &mut dyn ComponentTrait, context: &mut InContext) { if let Some(hook) = self.hook { hook(component, context) } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 205ea6cd..841632ba 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -2,7 +2,7 @@ use crate::{concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, html}; use crate::core::app; -use crate::core::component::{ComponentTrait, Context, Favicon}; +use crate::core::component::{ComponentTrait, Favicon, InContext}; use crate::response::page::Page; use crate::base::component::Chunck; @@ -86,7 +86,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn before_render_component( &self, component: &mut dyn ComponentTrait, - context: &mut Context + context: &mut InContext ) { /* Cómo usarlo: @@ -105,7 +105,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { fn render_component( &self, component: &dyn ComponentTrait, - context: &mut Context + context: &mut InContext ) -> Option { None /* diff --git a/pagetop/src/response/page/definition.rs b/pagetop/src/response/page/definition.rs index f57de4ee..ce1ab12b 100644 --- a/pagetop/src/response/page/definition.rs +++ b/pagetop/src/response/page/definition.rs @@ -42,8 +42,8 @@ pub struct Page<'a> { direction : OptAttr, title : OptAttr, description : OptAttr, - context : Context, - regions : HashMap<&'a str, ComponentsHolder>, + context : InContext, + regions : HashMap<&'a str, ComponentsBundle>, body_classes: Classes, template : String, } @@ -62,7 +62,7 @@ impl<'a> Page<'a> { }, title : OptAttr::new(), description : OptAttr::new(), - context : Context::new(), + context : InContext::new(), regions : common_components(), body_classes: Classes::new_with_default("body"), template : "default".to_owned(), @@ -103,7 +103,7 @@ impl<'a> Page<'a> { if let Some(regions) = self.regions.get_mut(region) { regions.add(component); } else { - self.regions.insert(region, ComponentsHolder::new_with(component)); + self.regions.insert(region, ComponentsBundle::new_with(component)); } self } @@ -136,7 +136,7 @@ impl<'a> Page<'a> { self.description.option() } - pub fn context(&mut self) -> &mut Context { + pub fn context(&mut self) -> &mut InContext { &mut self.context } From 9485179257f0e324599975b1444499371338bf3d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 20:21:14 +0200 Subject: [PATCH 66/80] =?UTF-8?q?Actualiza=20la=20organizaci=C3=B3n=20del?= =?UTF-8?q?=20c=C3=B3digo=20para=20las=20apps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/{core => }/app.rs | 0 pagetop/src/{core => }/app/application.rs | 0 pagetop/src/{core => }/app/banner.rs | 0 pagetop/src/{core => }/app/banner/figfont.rs | 0 pagetop/src/{core => }/app/banner/slant.flf | 0 pagetop/src/{core => }/app/banner/small.flf | 0 pagetop/src/{core => }/app/banner/speed.flf | 0 pagetop/src/{core => }/app/banner/starwars.flf | 0 pagetop/src/{core => }/app/db.rs | 0 pagetop/src/{core => }/app/definition.rs | 0 pagetop/src/{core => }/app/locale.rs | 0 pagetop/src/{core => }/app/tracing.rs | 0 pagetop/src/core.rs | 1 - pagetop/src/core/module/all.rs | 3 +-- pagetop/src/core/module/definition.rs | 3 +-- pagetop/src/core/theme/all.rs | 3 +-- pagetop/src/core/theme/definition.rs | 3 +-- pagetop/src/lib.rs | 4 +++- pagetop/src/locale.rs | 2 +- pagetop/src/prelude.rs | 7 ++++--- pagetop/src/response/page/definition.rs | 3 +-- 21 files changed, 13 insertions(+), 16 deletions(-) rename pagetop/src/{core => }/app.rs (100%) rename pagetop/src/{core => }/app/application.rs (100%) rename pagetop/src/{core => }/app/banner.rs (100%) rename pagetop/src/{core => }/app/banner/figfont.rs (100%) rename pagetop/src/{core => }/app/banner/slant.flf (100%) rename pagetop/src/{core => }/app/banner/small.flf (100%) rename pagetop/src/{core => }/app/banner/speed.flf (100%) rename pagetop/src/{core => }/app/banner/starwars.flf (100%) rename pagetop/src/{core => }/app/db.rs (100%) rename pagetop/src/{core => }/app/definition.rs (100%) rename pagetop/src/{core => }/app/locale.rs (100%) rename pagetop/src/{core => }/app/tracing.rs (100%) diff --git a/pagetop/src/core/app.rs b/pagetop/src/app.rs similarity index 100% rename from pagetop/src/core/app.rs rename to pagetop/src/app.rs diff --git a/pagetop/src/core/app/application.rs b/pagetop/src/app/application.rs similarity index 100% rename from pagetop/src/core/app/application.rs rename to pagetop/src/app/application.rs diff --git a/pagetop/src/core/app/banner.rs b/pagetop/src/app/banner.rs similarity index 100% rename from pagetop/src/core/app/banner.rs rename to pagetop/src/app/banner.rs diff --git a/pagetop/src/core/app/banner/figfont.rs b/pagetop/src/app/banner/figfont.rs similarity index 100% rename from pagetop/src/core/app/banner/figfont.rs rename to pagetop/src/app/banner/figfont.rs diff --git a/pagetop/src/core/app/banner/slant.flf b/pagetop/src/app/banner/slant.flf similarity index 100% rename from pagetop/src/core/app/banner/slant.flf rename to pagetop/src/app/banner/slant.flf diff --git a/pagetop/src/core/app/banner/small.flf b/pagetop/src/app/banner/small.flf similarity index 100% rename from pagetop/src/core/app/banner/small.flf rename to pagetop/src/app/banner/small.flf diff --git a/pagetop/src/core/app/banner/speed.flf b/pagetop/src/app/banner/speed.flf similarity index 100% rename from pagetop/src/core/app/banner/speed.flf rename to pagetop/src/app/banner/speed.flf diff --git a/pagetop/src/core/app/banner/starwars.flf b/pagetop/src/app/banner/starwars.flf similarity index 100% rename from pagetop/src/core/app/banner/starwars.flf rename to pagetop/src/app/banner/starwars.flf diff --git a/pagetop/src/core/app/db.rs b/pagetop/src/app/db.rs similarity index 100% rename from pagetop/src/core/app/db.rs rename to pagetop/src/app/db.rs diff --git a/pagetop/src/core/app/definition.rs b/pagetop/src/app/definition.rs similarity index 100% rename from pagetop/src/core/app/definition.rs rename to pagetop/src/app/definition.rs diff --git a/pagetop/src/core/app/locale.rs b/pagetop/src/app/locale.rs similarity index 100% rename from pagetop/src/core/app/locale.rs rename to pagetop/src/app/locale.rs diff --git a/pagetop/src/core/app/tracing.rs b/pagetop/src/app/tracing.rs similarity index 100% rename from pagetop/src/core/app/tracing.rs rename to pagetop/src/app/tracing.rs diff --git a/pagetop/src/core.rs b/pagetop/src/core.rs index e3208027..7b25095b 100644 --- a/pagetop/src/core.rs +++ b/pagetop/src/core.rs @@ -1,4 +1,3 @@ -pub mod app; // API to initialize the PageTop base application. pub mod component; // API to build new components. pub mod hook; // API to define functions that alter the behavior of PageTop core. pub mod module; // API to add new features with modules. diff --git a/pagetop/src/core/module/all.rs b/pagetop/src/core/module/all.rs index 5131a878..1a20688c 100644 --- a/pagetop/src/core/module/all.rs +++ b/pagetop/src/core/module/all.rs @@ -1,5 +1,4 @@ -use crate::{Lazy, run_now, trace}; -use crate::core::app; +use crate::{Lazy, app, run_now, trace}; use crate::core::hook::add_hook; use crate::db::*; use super::ModuleTrait; diff --git a/pagetop/src/core/module/definition.rs b/pagetop/src/core/module/definition.rs index 89904cc0..38621d82 100644 --- a/pagetop/src/core/module/definition.rs +++ b/pagetop/src/core/module/definition.rs @@ -1,5 +1,4 @@ -use crate::util; -use crate::core::app; +use crate::{app, util}; use crate::core::hook::HookItem; #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] diff --git a/pagetop/src/core/theme/all.rs b/pagetop/src/core/theme/all.rs index dc693e70..2a02b2ec 100644 --- a/pagetop/src/core/theme/all.rs +++ b/pagetop/src/core/theme/all.rs @@ -1,5 +1,4 @@ -use crate::{Lazy, theme_static_files, trace}; -use crate::core::app; +use crate::{Lazy, app, theme_static_files, trace}; use super::ThemeTrait; use std::sync::RwLock; diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 841632ba..951c7a50 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -1,7 +1,6 @@ -use crate::{concat_string, util}; +use crate::{app, concat_string, util}; use crate::config::SETTINGS; use crate::html::{Markup, html}; -use crate::core::app; use crate::core::component::{ComponentTrait, Favicon, InContext}; use crate::response::page::Page; use crate::base::component::Chunck; diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index c4081535..79b3e3e5 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -18,7 +18,9 @@ pub mod html; // HTML en código. #[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] pub mod db; // Acceso a base de datos. -pub mod core; // Main APIs for app, components, hooks, modules and themes. +pub mod app; // Prepare and run the application. + +pub mod core; // Main APIs for components, hooks, modules and themes. pub mod response; // Tipos de respuestas web. pub mod base; // Base de componentes, módulos y temas. diff --git a/pagetop/src/locale.rs b/pagetop/src/locale.rs index 98e88823..93e9e7e8 100644 --- a/pagetop/src/locale.rs +++ b/pagetop/src/locale.rs @@ -7,7 +7,7 @@ pub use fluent_templates::fluent_bundle::FluentValue; macro_rules! localize { ( $dir_locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; - use $crate::core::app::locale::LANGID; + use $crate::app::locale::LANGID; static_locale! { static LOCALES = { diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index e9b8a396..c772c91d 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -21,15 +21,16 @@ pub use crate::{ migration_item, }; +pub use crate::app; +pub use crate::app::AppTrait; +pub use crate::app::application::Application; + pub use crate::{hook_item, core::{ - app, component::*, hook::*, module::*, theme::*, }}; -pub use crate::core::app::AppTrait; -pub use crate::core::app::application::Application; pub use crate::response::page::*; diff --git a/pagetop/src/response/page/definition.rs b/pagetop/src/response/page/definition.rs index ce1ab12b..fb9f0fa8 100644 --- a/pagetop/src/response/page/definition.rs +++ b/pagetop/src/response/page/definition.rs @@ -1,7 +1,6 @@ -use crate::{Lazy, trace}; +use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::core::app; use crate::core::hook::{hook_ref, run_hooks}; use crate::core::component::*; use super::{BEFORE_RENDER_PAGE_HOOK, BeforeRenderPageHook}; From aab74546ed857352050cf049f2cdb4d42caa0497 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 20:53:19 +0200 Subject: [PATCH 67/80] =?UTF-8?q?Retoca=20la=20disposici=C3=B3n=20de=20los?= =?UTF-8?q?=20elementos=20de=20contexto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/core/component/context.rs | 166 +++++++++++++++++- pagetop/src/core/component/context/favicon.rs | 86 --------- .../src/core/component/context/javascript.rs | 43 ----- .../src/core/component/context/stylesheet.rs | 29 --- 4 files changed, 159 insertions(+), 165 deletions(-) delete mode 100644 pagetop/src/core/component/context/favicon.rs delete mode 100644 pagetop/src/core/component/context/javascript.rs delete mode 100644 pagetop/src/core/component/context/stylesheet.rs diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs index a5c7a43a..9b788557 100644 --- a/pagetop/src/core/component/context.rs +++ b/pagetop/src/core/component/context.rs @@ -1,16 +1,168 @@ use crate::{Lazy, base, concat_string, util}; use crate::config::SETTINGS; -use crate::html::{Markup, html}; +use crate::html::{Markup, PreEscaped, html}; use crate::core::theme::*; -mod favicon; -pub use favicon::Favicon; +// Favicon. -mod javascript; -pub use javascript::{JavaScript, JSMode}; +pub struct Favicon(Vec); -mod stylesheet; -pub use stylesheet::StyleSheet; +impl Favicon { + pub fn new() -> Self { + Favicon(Vec::new()) + } + + pub fn with_icon(self, image: &str) -> Self { + self.add_item("icon", image, "", "") + } + + pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { + self.add_item("icon", image, sizes, "") + } + + pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { + self.add_item("apple-touch-icon", image, sizes, "") + } + + pub fn with_mask_icon(self, image: &str, color: &str) -> Self { + self.add_item("mask-icon", image, "", color) + } + + pub fn with_manifest(self, file: &str) -> Self { + self.add_item("manifest", file, "", "") + } + + pub fn with_theme_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_image(mut self, image: &str) -> Self { + self.0.push(format!( + "", image + )); + self + } + + fn add_item( + mut self, + rel : &str, + source: &str, + sizes : &str, + color : &str + ) -> Self { + let mut link: String = format!(" format!("{} type=\"image/gif\"", link), + ".ico" => format!("{} type=\"image/x-icon\"", link), + ".jpg" => format!("{} type=\"image/jpg\"", link), + ".png" => format!("{} type=\"image/png\"", link), + ".svg" => format!("{} type=\"image/svg+xml\"", link), + _ => link + }; + } + if !sizes.is_empty() { + link = format!("{} sizes=\"{}\"", link, sizes); + } + if !color.is_empty() { + link = format!("{} color=\"{}\"", link, color); + } + self.0.push(format!("{} href=\"{}\">", link, source)); + self + } + + fn render(&self) -> Markup { + html! { + @for item in &self.0 { + (PreEscaped(item)) + } + } + } +} + +// JavaScript. + +#[derive(PartialEq)] +pub enum JSMode { Async, Defer, Normal } + +pub struct JavaScript { + source: &'static str, + weight: isize, + mode : JSMode, +} +impl JavaScript { + pub fn source(s: &'static str) -> Self { + JavaScript { + source: s, + weight: 0, + mode : JSMode::Defer, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn with_mode(mut self, mode: JSMode) -> Self { + self.mode = mode; + self + } + + pub fn weight(self) -> isize { + self.weight + } + + pub fn render(&self) -> Markup { + html! { + script type="text/javascript" + src=(self.source) + async[self.mode == JSMode::Async] + defer[self.mode == JSMode::Defer] + {}; + } + } +} + +// StyleSheet. + +pub struct StyleSheet { + source: &'static str, + weight: isize, +} +impl StyleSheet { + pub fn source(s: &'static str) -> Self { + StyleSheet { + source: s, + weight: 0, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn weight(self) -> isize { + self.weight + } + + fn render(&self) -> Markup { + html! { + link rel="stylesheet" href=(self.source); + } + } +} static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { match all::theme_by_single_name(&SETTINGS.app.theme) { diff --git a/pagetop/src/core/component/context/favicon.rs b/pagetop/src/core/component/context/favicon.rs deleted file mode 100644 index 1788540e..00000000 --- a/pagetop/src/core/component/context/favicon.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::html::{Markup, PreEscaped, html}; - -pub struct Favicon(Vec); - -impl Favicon { - pub fn new() -> Self { - Favicon(Vec::new()) - } - - pub fn with_icon(self, image: &str) -> Self { - self.add_item("icon", image, "", "") - } - - pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { - self.add_item("icon", image, sizes, "") - } - - pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { - self.add_item("apple-touch-icon", image, sizes, "") - } - - pub fn with_mask_icon(self, image: &str, color: &str) -> Self { - self.add_item("mask-icon", image, "", color) - } - - pub fn with_manifest(self, file: &str) -> Self { - self.add_item("manifest", file, "", "") - } - - pub fn with_theme_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_image(mut self, image: &str) -> Self { - self.0.push(format!( - "", image - )); - self - } - - fn add_item( - mut self, - rel : &str, - source: &str, - sizes : &str, - color : &str - ) -> Self { - let mut link: String = format!(" format!("{} type=\"image/gif\"", link), - ".ico" => format!("{} type=\"image/x-icon\"", link), - ".jpg" => format!("{} type=\"image/jpg\"", link), - ".png" => format!("{} type=\"image/png\"", link), - ".svg" => format!("{} type=\"image/svg+xml\"", link), - _ => link - }; - } - if !sizes.is_empty() { - link = format!("{} sizes=\"{}\"", link, sizes); - } - if !color.is_empty() { - link = format!("{} color=\"{}\"", link, color); - } - self.0.push(format!("{} href=\"{}\">", link, source)); - self - } - - pub(super) fn render(&self) -> Markup { - html! { - @for item in &self.0 { - (PreEscaped(item)) - } - } - } -} diff --git a/pagetop/src/core/component/context/javascript.rs b/pagetop/src/core/component/context/javascript.rs deleted file mode 100644 index 2f2d725b..00000000 --- a/pagetop/src/core/component/context/javascript.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::html::{Markup, html}; - -#[derive(PartialEq)] -pub enum JSMode { Async, Defer, Normal } - -pub struct JavaScript { - pub(super) source: &'static str, - pub(super) weight: isize, - pub(super) mode : JSMode, -} -impl JavaScript { - pub fn source(s: &'static str) -> Self { - JavaScript { - source: s, - weight: 0, - mode : JSMode::Defer, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn with_mode(mut self, mode: JSMode) -> Self { - self.mode = mode; - self - } - - pub fn weight(self) -> isize { - self.weight - } - - pub(super) fn render(&self) -> Markup { - html! { - script type="text/javascript" - src=(self.source) - async[self.mode == JSMode::Async] - defer[self.mode == JSMode::Defer] - {}; - } - } -} diff --git a/pagetop/src/core/component/context/stylesheet.rs b/pagetop/src/core/component/context/stylesheet.rs deleted file mode 100644 index f7803938..00000000 --- a/pagetop/src/core/component/context/stylesheet.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::html::{Markup, html}; - -pub struct StyleSheet { - pub(super) source: &'static str, - pub(super) weight: isize, -} -impl StyleSheet { - pub fn source(s: &'static str) -> Self { - StyleSheet { - source: s, - weight: 0, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn weight(self) -> isize { - self.weight - } - - pub(super) fn render(&self) -> Markup { - html! { - link rel="stylesheet" href=(self.source); - } - } -} From 9f6b790a9d39fdb2e0af88c3f13a051956dd5c01 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 20:54:40 +0200 Subject: [PATCH 68/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index d044369c..6bde05af 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.14" +version = "0.0.15" edition = "2021" authors = [ From 18bec0543c2152da29217bbfaaabdedb41591713 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 15 May 2022 22:18:28 +0200 Subject: [PATCH 69/80] Modifica la fuente de los activos globales --- pagetop/src/base/component/menu.rs | 6 +++--- pagetop/src/base/theme/aliner.rs | 2 +- pagetop/src/base/theme/bootsier.rs | 4 ++-- pagetop/src/base/theme/bulmix.rs | 2 +- pagetop/src/core/component/context.rs | 16 ++++------------ pagetop/src/core/component/definition.rs | 2 +- pagetop/src/response/page/definition.rs | 2 +- 7 files changed, 13 insertions(+), 21 deletions(-) diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index ef7668aa..22902ed2 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -208,13 +208,13 @@ impl ComponentTrait for Menu { fn default_render(&self, context: &mut InContext) -> Markup { context - .add_stylesheet(StyleSheet::source( + .add_stylesheet(StyleSheet::with_source( "/theme/menu/css/menu.css?ver=1.1.1" )) - .add_stylesheet(StyleSheet::source( + .add_stylesheet(StyleSheet::with_source( "/theme/menu/css/menu-clean.css?ver=1.1.1" )) - .add_javascript(JavaScript::source( + .add_javascript(JavaScript::with_source( "/theme/menu/js/menu.min.js?ver=1.1.1" )) .add_jquery(); diff --git a/pagetop/src/base/theme/aliner.rs b/pagetop/src/base/theme/aliner.rs index ae6c7475..e4180303 100644 --- a/pagetop/src/base/theme/aliner.rs +++ b/pagetop/src/base/theme/aliner.rs @@ -22,7 +22,7 @@ impl ThemeTrait for Aliner { .with_icon("/theme/favicon.png") ) .add_stylesheet( - StyleSheet::source( + StyleSheet::with_source( "/aliner/css/styles.css" ) .with_weight(-99) diff --git a/pagetop/src/base/theme/bootsier.rs b/pagetop/src/base/theme/bootsier.rs index 494bda17..ec294457 100644 --- a/pagetop/src/base/theme/bootsier.rs +++ b/pagetop/src/base/theme/bootsier.rs @@ -24,13 +24,13 @@ impl ThemeTrait for Bootsier { .with_icon("/theme/favicon.png") ) .add_stylesheet( - StyleSheet::source( + StyleSheet::with_source( "/bootsier/css/bootstrap.min.css?ver=5.1.3" ) .with_weight(-99) ) .add_javascript( - JavaScript::source( + JavaScript::with_source( "/bootsier/js/bootstrap.bundle.min.js?ver=5.1.3" ) .with_weight(-99) diff --git a/pagetop/src/base/theme/bulmix.rs b/pagetop/src/base/theme/bulmix.rs index f099d880..9dfde724 100644 --- a/pagetop/src/base/theme/bulmix.rs +++ b/pagetop/src/base/theme/bulmix.rs @@ -22,7 +22,7 @@ impl ThemeTrait for Bulmix { .with_icon("/theme/favicon.png") ) .add_stylesheet( - StyleSheet::source( + StyleSheet::with_source( "/bulmix/css/bulma.min.css?ver=0.9.3" ) .with_weight(-99) diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs index 9b788557..6fcf7be8 100644 --- a/pagetop/src/core/component/context.rs +++ b/pagetop/src/core/component/context.rs @@ -101,7 +101,7 @@ pub struct JavaScript { mode : JSMode, } impl JavaScript { - pub fn source(s: &'static str) -> Self { + pub fn with_source(s: &'static str) -> Self { JavaScript { source: s, weight: 0, @@ -119,11 +119,7 @@ impl JavaScript { self } - pub fn weight(self) -> isize { - self.weight - } - - pub fn render(&self) -> Markup { + fn render(&self) -> Markup { html! { script type="text/javascript" src=(self.source) @@ -141,7 +137,7 @@ pub struct StyleSheet { weight: isize, } impl StyleSheet { - pub fn source(s: &'static str) -> Self { + pub fn with_source(s: &'static str) -> Self { StyleSheet { source: s, weight: 0, @@ -153,10 +149,6 @@ impl StyleSheet { self } - pub fn weight(self) -> isize { - self.weight - } - fn render(&self) -> Markup { html! { link rel="stylesheet" href=(self.source); @@ -234,7 +226,7 @@ impl InContext { pub fn add_jquery(&mut self) -> &mut Self { if !self.with_jquery { self.add_javascript( - JavaScript::source( + JavaScript::with_source( "/theme/js/jquery.min.js?ver=3.6.0" ) .with_weight(isize::MIN) diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index 96950798..4912214e 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -55,7 +55,7 @@ pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InCont // Acciones de los módulos antes de renderizar el componente. run_hooks( BEFORE_RENDER_COMPONENT_HOOK, - |a| hook_ref::(&**a).run(component, context) + |hook| hook_ref::(&**hook).run(component, context) ); // Acciones del tema antes de renderizar el componente. diff --git a/pagetop/src/response/page/definition.rs b/pagetop/src/response/page/definition.rs index fb9f0fa8..ba210d2d 100644 --- a/pagetop/src/response/page/definition.rs +++ b/pagetop/src/response/page/definition.rs @@ -153,7 +153,7 @@ impl<'a> Page<'a> { // Acciones de los módulos antes de renderizar la página. run_hooks( BEFORE_RENDER_PAGE_HOOK, - |a| hook_ref::(&**a).run(self) + |hook| hook_ref::(&**hook).run(self) ); // Acciones del tema antes de renderizar la página. From 658d88a383b554e3ffaf510ae401cd8a13cad69c Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 16 May 2022 18:41:51 +0200 Subject: [PATCH 70/80] Elimina before_render() en la def. de componentes --- pagetop/src/base/component/form/input.rs | 23 +++++------------------ pagetop/src/core/component/definition.rs | 7 ------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index c96197e8..18a980e3 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -47,7 +47,6 @@ impl ComponentTrait for Input { classes : Classes::new_with_default("form-item"), template : "default".to_owned(), } - .with_classes("form-type-textfield", ClassesOp::AddFirst) } fn handler(&self) -> &'static str { @@ -62,13 +61,6 @@ impl ComponentTrait for Input { self.weight } - fn before_render(&mut self, _: &mut InContext) { - if let Some(name) = self.name() { - let class = concat_string!("form-item-", name); - self.alter_classes(class.as_str(), ClassesOp::AddFirst); - } - } - fn default_render(&self, _: &mut InContext) -> Markup { let type_input = match self.input_type() { InputType::Email => "email", @@ -134,36 +126,31 @@ impl Input { } pub fn password() -> Self { - let mut input = Input::new() - .with_classes("form-type-password", ClassesOp::Replace("form-type-textfield")); + let mut input = Input::new(); input.input_type = InputType::Password; input } pub fn search() -> Self { - let mut input = Input::new() - .with_classes("form-type-search", ClassesOp::Replace("form-type-textfield")); + let mut input = Input::new(); input.input_type = InputType::Search; input } pub fn email() -> Self { - let mut input = Input::new() - .with_classes("form-type-email", ClassesOp::Replace("form-type-textfield")); + let mut input = Input::new(); input.input_type = InputType::Email; input } pub fn telephone() -> Self { - let mut input = Input::new() - .with_classes("form-type-telephone", ClassesOp::Replace("form-type-textfield")); + let mut input = Input::new(); input.input_type = InputType::Telephone; input } pub fn url() -> Self { - let mut input = Input::new() - .with_classes("form-type-url", ClassesOp::Replace("form-type-textfield")); + let mut input = Input::new(); input.input_type = InputType::Url; input } diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index 4912214e..4b49526f 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -26,10 +26,6 @@ pub trait ComponentTrait: AnyComponent + Send + Sync { 0 } - #[allow(unused_variables)] - fn before_render(&mut self, context: &mut InContext) { - } - #[allow(unused_variables)] fn default_render(&self, context: &mut InContext) -> Markup { html! {} @@ -49,9 +45,6 @@ pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { } pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InContext) -> Markup { - // Acciones del componente antes de renderizar. - component.before_render(context); - // Acciones de los módulos antes de renderizar el componente. run_hooks( BEFORE_RENDER_COMPONENT_HOOK, From f5314e9ca4caa126db5729521fac99c99ca51750 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 16 May 2022 20:44:17 +0200 Subject: [PATCH 71/80] =?UTF-8?q?Modifica=20la=20localizaci=C3=B3n=20de=20?= =?UTF-8?q?activos=20en=20el=20contexto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component/form/input.rs | 20 ++- pagetop/src/base/theme/aliner.rs | 7 +- pagetop/src/base/theme/bootsier.rs | 7 +- pagetop/src/base/theme/bulmix.rs | 7 +- pagetop/src/core/component.rs | 5 - pagetop/src/core/component/context.rs | 204 ++--------------------- pagetop/src/core/theme/definition.rs | 11 +- pagetop/src/html.rs | 10 ++ pagetop/src/html/assets.rs | 41 +++++ pagetop/src/html/assets/javascript.rs | 51 ++++++ pagetop/src/html/assets/stylesheet.rs | 37 ++++ pagetop/src/html/favicon.rs | 86 ++++++++++ 12 files changed, 269 insertions(+), 217 deletions(-) create mode 100644 pagetop/src/html/assets.rs create mode 100644 pagetop/src/html/assets/javascript.rs create mode 100644 pagetop/src/html/assets/stylesheet.rs create mode 100644 pagetop/src/html/favicon.rs diff --git a/pagetop/src/base/component/form/input.rs b/pagetop/src/base/component/form/input.rs index 18a980e3..0c615de2 100644 --- a/pagetop/src/base/component/form/input.rs +++ b/pagetop/src/base/component/form/input.rs @@ -47,6 +47,7 @@ impl ComponentTrait for Input { classes : Classes::new_with_default("form-item"), template : "default".to_owned(), } + .with_classes("form-type-textfield", ClassesOp::AddFirst) } fn handler(&self) -> &'static str { @@ -126,31 +127,36 @@ impl Input { } pub fn password() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-password", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Password; input } pub fn search() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-search", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Search; input } pub fn email() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-email", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Email; input } pub fn telephone() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-telephone", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Telephone; input } pub fn url() -> Self { - let mut input = Input::new(); + let mut input = Input::new() + .with_classes("form-type-url", ClassesOp::Replace("form-type-textfield")); input.input_type = InputType::Url; input } @@ -256,6 +262,10 @@ impl Input { pub fn alter_name(&mut self, name: &str) -> &mut Self { self.name.with_value(name); + self.alter_classes( + concat_string!("form-item form-item-", name).as_str(), + ClassesOp::SetDefault + ); self } diff --git a/pagetop/src/base/theme/aliner.rs b/pagetop/src/base/theme/aliner.rs index e4180303..02ed19d3 100644 --- a/pagetop/src/base/theme/aliner.rs +++ b/pagetop/src/base/theme/aliner.rs @@ -17,10 +17,9 @@ impl ThemeTrait for Aliner { fn before_render_page(&self, page: &mut Page) { page.context() - .with_favicon( - Favicon::new() - .with_icon("/theme/favicon.png") - ) + .with_favicon(Some(Favicon::new() + .with_icon("/theme/favicon.png") + )) .add_stylesheet( StyleSheet::with_source( "/aliner/css/styles.css" diff --git a/pagetop/src/base/theme/bootsier.rs b/pagetop/src/base/theme/bootsier.rs index ec294457..8512234f 100644 --- a/pagetop/src/base/theme/bootsier.rs +++ b/pagetop/src/base/theme/bootsier.rs @@ -19,10 +19,9 @@ impl ThemeTrait for Bootsier { fn before_render_page(&self, page: &mut Page) { page.context() - .with_favicon( - Favicon::new() - .with_icon("/theme/favicon.png") - ) + .with_favicon(Some(Favicon::new() + .with_icon("/theme/favicon.png") + )) .add_stylesheet( StyleSheet::with_source( "/bootsier/css/bootstrap.min.css?ver=5.1.3" diff --git a/pagetop/src/base/theme/bulmix.rs b/pagetop/src/base/theme/bulmix.rs index 9dfde724..a1b98275 100644 --- a/pagetop/src/base/theme/bulmix.rs +++ b/pagetop/src/base/theme/bulmix.rs @@ -17,10 +17,9 @@ impl ThemeTrait for Bulmix { fn before_render_page(&self, page: &mut Page) { page.context() - .with_favicon( - Favicon::new() - .with_icon("/theme/favicon.png") - ) + .with_favicon(Some(Favicon::new() + .with_icon("/theme/favicon.png") + )) .add_stylesheet( StyleSheet::with_source( "/bulmix/css/bulma.min.css?ver=0.9.3" diff --git a/pagetop/src/core/component.rs b/pagetop/src/core/component.rs index 038ee93d..ef3e33d5 100644 --- a/pagetop/src/core/component.rs +++ b/pagetop/src/core/component.rs @@ -6,11 +6,6 @@ pub use hook::{ mod context; pub use context::InContext; -pub use context::{ - Favicon, - JavaScript, JSMode, - StyleSheet, -}; mod definition; pub use definition::{ diff --git a/pagetop/src/core/component/context.rs b/pagetop/src/core/component/context.rs index 6fcf7be8..916d0d96 100644 --- a/pagetop/src/core/component/context.rs +++ b/pagetop/src/core/component/context.rs @@ -1,163 +1,11 @@ use crate::{Lazy, base, concat_string, util}; use crate::config::SETTINGS; -use crate::html::{Markup, PreEscaped, html}; -use crate::core::theme::*; - -// Favicon. - -pub struct Favicon(Vec); - -impl Favicon { - pub fn new() -> Self { - Favicon(Vec::new()) - } - - pub fn with_icon(self, image: &str) -> Self { - self.add_item("icon", image, "", "") - } - - pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { - self.add_item("icon", image, sizes, "") - } - - pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { - self.add_item("apple-touch-icon", image, sizes, "") - } - - pub fn with_mask_icon(self, image: &str, color: &str) -> Self { - self.add_item("mask-icon", image, "", color) - } - - pub fn with_manifest(self, file: &str) -> Self { - self.add_item("manifest", file, "", "") - } - - pub fn with_theme_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_color(mut self, color: &str) -> Self { - self.0.push(format!( - "", color - )); - self - } - - pub fn with_ms_tile_image(mut self, image: &str) -> Self { - self.0.push(format!( - "", image - )); - self - } - - fn add_item( - mut self, - rel : &str, - source: &str, - sizes : &str, - color : &str - ) -> Self { - let mut link: String = format!(" format!("{} type=\"image/gif\"", link), - ".ico" => format!("{} type=\"image/x-icon\"", link), - ".jpg" => format!("{} type=\"image/jpg\"", link), - ".png" => format!("{} type=\"image/png\"", link), - ".svg" => format!("{} type=\"image/svg+xml\"", link), - _ => link - }; - } - if !sizes.is_empty() { - link = format!("{} sizes=\"{}\"", link, sizes); - } - if !color.is_empty() { - link = format!("{} color=\"{}\"", link, color); - } - self.0.push(format!("{} href=\"{}\">", link, source)); - self - } - - fn render(&self) -> Markup { - html! { - @for item in &self.0 { - (PreEscaped(item)) - } - } - } -} - -// JavaScript. - -#[derive(PartialEq)] -pub enum JSMode { Async, Defer, Normal } - -pub struct JavaScript { - source: &'static str, - weight: isize, - mode : JSMode, -} -impl JavaScript { - pub fn with_source(s: &'static str) -> Self { - JavaScript { - source: s, - weight: 0, - mode : JSMode::Defer, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn with_mode(mut self, mode: JSMode) -> Self { - self.mode = mode; - self - } - - fn render(&self) -> Markup { - html! { - script type="text/javascript" - src=(self.source) - async[self.mode == JSMode::Async] - defer[self.mode == JSMode::Defer] - {}; - } - } -} - -// StyleSheet. - -pub struct StyleSheet { - source: &'static str, - weight: isize, -} -impl StyleSheet { - pub fn with_source(s: &'static str) -> Self { - StyleSheet { - source: s, - weight: 0, - } - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - fn render(&self) -> Markup { - html! { - link rel="stylesheet" href=(self.source); - } - } -} +use crate::html::*; +use crate::core::theme::ThemeTrait; +use crate::core::theme::all::theme_by_single_name; static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| { - match all::theme_by_single_name(&SETTINGS.app.theme) { + match theme_by_single_name(&SETTINGS.app.theme) { Some(theme) => theme, None => &base::theme::bootsier::Bootsier, } @@ -167,8 +15,8 @@ pub struct InContext { theme : &'static dyn ThemeTrait, favicon : Option, metadata : Vec<(String, String)>, - stylesheets: Vec, - javascripts: Vec, + stylesheets: Assets, + javascripts: Assets, with_jquery: bool, id_counter : usize, } @@ -179,20 +27,20 @@ impl InContext { theme : *DEFAULT_THEME, favicon : None, metadata : Vec::new(), - stylesheets: Vec::new(), - javascripts: Vec::new(), + stylesheets: Assets::::new(), + javascripts: Assets::::new(), with_jquery: false, id_counter : 0, } } pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { - self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); + self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); self } - pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self { - self.favicon = Some(favicon); + pub fn with_favicon(&mut self, favicon: Option) -> &mut Self { + self.favicon = favicon; self } @@ -202,24 +50,12 @@ impl InContext { } pub fn add_stylesheet(&mut self, css: StyleSheet) -> &mut Self { - match self.stylesheets.iter().position(|x| x.source == css.source) { - Some(index) => if self.stylesheets[index].weight > css.weight { - self.stylesheets.remove(index); - self.stylesheets.push(css); - }, - _ => self.stylesheets.push(css) - } + self.stylesheets.add(css); self } pub fn add_javascript(&mut self, js: JavaScript) -> &mut Self { - match self.javascripts.iter().position(|x| x.source == js.source) { - Some(index) => if self.javascripts[index].weight > js.weight { - self.javascripts.remove(index); - self.javascripts.push(js); - }, - _ => self.javascripts.push(js) - } + self.javascripts.add(js); self } @@ -246,12 +82,6 @@ impl InContext { /// InContext RENDER. pub fn render(&mut self) -> Markup { - let ordered_css = &mut self.stylesheets; - ordered_css.sort_by_key(|css| css.weight); - - let ordered_js = &mut self.javascripts; - ordered_js.sort_by_key(|js| js.weight); - html! { @match &self.favicon { Some(favicon) => (favicon.render()), @@ -260,12 +90,8 @@ impl InContext { @for (name, content) in &self.metadata { meta name=(name) content=(content) {} } - @for css in ordered_css { - (css.render()) - } - @for js in ordered_js { - (js.render()) - } + (self.stylesheets.render()) + (self.javascripts.render()) } } diff --git a/pagetop/src/core/theme/definition.rs b/pagetop/src/core/theme/definition.rs index 951c7a50..520eadc4 100644 --- a/pagetop/src/core/theme/definition.rs +++ b/pagetop/src/core/theme/definition.rs @@ -1,7 +1,7 @@ use crate::{app, concat_string, util}; use crate::config::SETTINGS; -use crate::html::{Markup, html}; -use crate::core::component::{ComponentTrait, Favicon, InContext}; +use crate::html::{Favicon, Markup, html}; +use crate::core::component::{ComponentTrait, InContext}; use crate::response::page::Page; use crate::base::component::Chunck; @@ -28,10 +28,9 @@ pub trait ThemeTrait: BaseTheme + Send + Sync { #[allow(unused_variables)] fn before_render_page(&self, page: &mut Page) { page.context() - .with_favicon( - Favicon::new() - .with_icon("/theme/favicon.png") - ); + .with_favicon(Some(Favicon::new() + .with_icon("/theme/favicon.png") + )); } fn render_page_head(&self, page: &mut Page) -> Markup { diff --git a/pagetop/src/html.rs b/pagetop/src/html.rs index 56e5c6d2..0afcdadd 100644 --- a/pagetop/src/html.rs +++ b/pagetop/src/html.rs @@ -1,8 +1,18 @@ pub use maud::{DOCTYPE, Markup, PreEscaped, html}; +mod assets; +pub use assets::Assets; +pub use assets::javascript::{JavaScript, JSMode}; +pub use assets::stylesheet::StyleSheet; + +mod favicon; +pub use favicon::Favicon; + mod optiden; pub use optiden::OptIden; + mod optattr; pub use optattr::OptAttr; + mod classes; pub use classes::{Classes, ClassesOp}; diff --git a/pagetop/src/html/assets.rs b/pagetop/src/html/assets.rs new file mode 100644 index 00000000..921d6816 --- /dev/null +++ b/pagetop/src/html/assets.rs @@ -0,0 +1,41 @@ +pub mod javascript; +pub mod stylesheet; + +use crate::html::{Markup, html}; + +pub trait AssetsTrait { + fn source(&self) -> &'static str; + + fn weight(&self) -> isize; + + fn render(&self) -> Markup; +} + +pub struct Assets(Vec); + +impl Assets { + pub fn new() -> Self { + Assets::(Vec::::new()) + } + + pub fn add(&mut self, assets: T) -> &mut Self { + match self.0.iter().position(|x| x.source() == assets.source()) { + Some(index) => if self.0[index].weight() > assets.weight() { + self.0.remove(index); + self.0.push(assets); + }, + _ => self.0.push(assets) + } + self + } + + pub fn render(&mut self) -> Markup { + let assets = &mut self.0; + assets.sort_by_key(|a| a.weight()); + html! { + @for a in assets { + (a.render()) + } + } + } +} \ No newline at end of file diff --git a/pagetop/src/html/assets/javascript.rs b/pagetop/src/html/assets/javascript.rs new file mode 100644 index 00000000..40cdfb07 --- /dev/null +++ b/pagetop/src/html/assets/javascript.rs @@ -0,0 +1,51 @@ +use crate::html::{Markup, html}; +use super::AssetsTrait; + +#[derive(PartialEq)] +pub enum JSMode { Async, Defer, Normal } + +pub struct JavaScript { + source: &'static str, + weight: isize, + mode : JSMode, +} + +impl AssetsTrait for JavaScript { + fn source(&self) -> &'static str { + self.source + } + + fn weight(&self) -> isize { + self.weight + } + + fn render(&self) -> Markup { + html! { + script type="text/javascript" + src=(self.source) + async[self.mode == JSMode::Async] + defer[self.mode == JSMode::Defer] + {}; + } + } +} + +impl JavaScript { + pub fn with_source(s: &'static str) -> Self { + JavaScript { + source: s, + weight: 0, + mode : JSMode::Defer, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn with_mode(mut self, mode: JSMode) -> Self { + self.mode = mode; + self + } +} diff --git a/pagetop/src/html/assets/stylesheet.rs b/pagetop/src/html/assets/stylesheet.rs new file mode 100644 index 00000000..ff7da045 --- /dev/null +++ b/pagetop/src/html/assets/stylesheet.rs @@ -0,0 +1,37 @@ +use crate::html::{Markup, html}; +use super::AssetsTrait; + +pub struct StyleSheet { + source: &'static str, + weight: isize, +} + +impl AssetsTrait for StyleSheet { + fn source(&self) -> &'static str { + self.source + } + + fn weight(&self) -> isize { + self.weight + } + + fn render(&self) -> Markup { + html! { + link rel="stylesheet" href=(self.source); + } + } +} + +impl StyleSheet { + pub fn with_source(s: &'static str) -> Self { + StyleSheet { + source: s, + weight: 0, + } + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } +} diff --git a/pagetop/src/html/favicon.rs b/pagetop/src/html/favicon.rs new file mode 100644 index 00000000..d8d6fc18 --- /dev/null +++ b/pagetop/src/html/favicon.rs @@ -0,0 +1,86 @@ +use crate::html::{Markup, PreEscaped, html}; + +pub struct Favicon(Vec); + +impl Favicon { + pub fn new() -> Self { + Favicon(Vec::new()) + } + + pub fn with_icon(self, image: &str) -> Self { + self.add_item("icon", image, "", "") + } + + pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self { + self.add_item("icon", image, sizes, "") + } + + pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self { + self.add_item("apple-touch-icon", image, sizes, "") + } + + pub fn with_mask_icon(self, image: &str, color: &str) -> Self { + self.add_item("mask-icon", image, "", color) + } + + pub fn with_manifest(self, file: &str) -> Self { + self.add_item("manifest", file, "", "") + } + + pub fn with_theme_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_color(mut self, color: &str) -> Self { + self.0.push(format!( + "", color + )); + self + } + + pub fn with_ms_tile_image(mut self, image: &str) -> Self { + self.0.push(format!( + "", image + )); + self + } + + fn add_item( + mut self, + rel : &str, + source: &str, + sizes : &str, + color : &str + ) -> Self { + let mut link: String = format!(" format!("{} type=\"image/gif\"", link), + ".ico" => format!("{} type=\"image/x-icon\"", link), + ".jpg" => format!("{} type=\"image/jpg\"", link), + ".png" => format!("{} type=\"image/png\"", link), + ".svg" => format!("{} type=\"image/svg+xml\"", link), + _ => link + }; + } + if !sizes.is_empty() { + link = format!("{} sizes=\"{}\"", link, sizes); + } + if !color.is_empty() { + link = format!("{} color=\"{}\"", link, color); + } + self.0.push(format!("{} href=\"{}\">", link, source)); + self + } + + pub(crate) fn render(&self) -> Markup { + html! { + @for item in &self.0 { + (PreEscaped(item)) + } + } + } +} From 5901ff6fcf3c5307bd4dcd6a9102a6e2470ba371 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Mon, 16 May 2022 21:49:11 +0200 Subject: [PATCH 72/80] Corrige referencias si no se usa base de datos --- pagetop/src/core/module/all.rs | 9 +++++++-- pagetop/src/lib.rs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pagetop/src/core/module/all.rs b/pagetop/src/core/module/all.rs index 1a20688c..aae071a5 100644 --- a/pagetop/src/core/module/all.rs +++ b/pagetop/src/core/module/all.rs @@ -1,8 +1,13 @@ -use crate::{Lazy, app, run_now, trace}; +use crate::{Lazy, app, trace}; use crate::core::hook::add_hook; -use crate::db::*; use super::ModuleTrait; +#[cfg(any(feature = "mysql", feature = "postgres", feature = "sqlite"))] +use crate::{ + db::*, + run_now, +}; + use std::sync::RwLock; // Enabled modules. diff --git a/pagetop/src/lib.rs b/pagetop/src/lib.rs index 79b3e3e5..06dc32bc 100644 --- a/pagetop/src/lib.rs +++ b/pagetop/src/lib.rs @@ -6,6 +6,7 @@ pub use doc_comment::doc_comment; // Local. +#[allow(unused_imports)] pub(crate) use futures::executor::block_on as run_now; // Public APIs. From d5c1495fa2fae5d62d93ce8304e6c0bdcb4f52f3 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 17 May 2022 23:59:18 +0200 Subject: [PATCH 73/80] =?UTF-8?q?A=C3=B1ade=20un=20componente=20para=20ico?= =?UTF-8?q?nos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/src/base/component.rs | 6 +- pagetop/src/base/component/anchor.rs | 42 +- pagetop/src/base/component/icon.rs | 95 + pagetop/src/base/module/demopage.rs | 25 +- pagetop/src/core/component/bundle.rs | 4 + .../static/theme/icons/bootstrap-icons.css | 1705 +++++++++++++++++ .../static/theme/icons/bootstrap-icons.woff | Bin 0 -> 137216 bytes .../static/theme/icons/bootstrap-icons.woff2 | Bin 0 -> 102380 bytes 8 files changed, 1863 insertions(+), 14 deletions(-) create mode 100644 pagetop/src/base/component/icon.rs create mode 100644 pagetop/static/theme/icons/bootstrap-icons.css create mode 100644 pagetop/static/theme/icons/bootstrap-icons.woff create mode 100644 pagetop/static/theme/icons/bootstrap-icons.woff2 diff --git a/pagetop/src/base/component.rs b/pagetop/src/base/component.rs index 22caca38..b0fd2673 100644 --- a/pagetop/src/base/component.rs +++ b/pagetop/src/base/component.rs @@ -9,6 +9,10 @@ mod chunck; pub use chunck::{ CHUNCK_COMPONENT, Chunck }; +mod icon; +pub use icon::{ + ICON_COMPONENT, Icon +}; mod heading; pub use heading::{ HEADING_COMPONENT, Heading, HeadingDisplay, HeadingType @@ -19,7 +23,7 @@ pub use paragraph::{ }; mod anchor; pub use anchor::{ - ANCHOR_COMPONENT, Anchor, AnchorTarget, AnchorType + ANCHOR_COMPONENT, Anchor, AnchorIcon, AnchorTarget, AnchorType }; mod block; pub use block::{ diff --git a/pagetop/src/base/component/anchor.rs b/pagetop/src/base/component/anchor.rs index 0c100f04..50d1b41e 100644 --- a/pagetop/src/base/component/anchor.rs +++ b/pagetop/src/base/component/anchor.rs @@ -16,12 +16,16 @@ pub enum AnchorTarget { Top, } +pub type AnchorIcon = ComponentsBundle; + pub struct Anchor { renderable : fn() -> bool, weight : isize, anchor_type: AnchorType, href : OptAttr, html : Markup, + left_icon : AnchorIcon, + right_icon : AnchorIcon, target : AnchorTarget, id : OptIden, classes : Classes, @@ -36,6 +40,8 @@ impl ComponentTrait for Anchor { anchor_type: AnchorType::Link, href : OptAttr::new(), html : html! {}, + left_icon : AnchorIcon::new(), + right_icon : AnchorIcon::new(), target : AnchorTarget::Default, id : OptIden::new(), classes : Classes::new(), @@ -55,7 +61,7 @@ impl ComponentTrait for Anchor { self.weight } - fn default_render(&self, _: &mut InContext) -> Markup { + fn default_render(&self, context: &mut InContext) -> Markup { let target = match &self.target() { AnchorTarget::Blank => Some("_blank"), AnchorTarget::Context(name) => Some(name.as_str()), @@ -70,7 +76,9 @@ impl ComponentTrait for Anchor { href=[self.href()] target=[target] { - (*self.html()) + (self.left_icon().render(context)) + (" ")(*self.html())(" ") + (self.right_icon().render(context)) } } } @@ -124,6 +132,16 @@ impl Anchor { self } + pub fn with_left_icon(mut self, icon: Icon) -> Self { + self.alter_left_icon(icon); + self + } + + pub fn with_right_icon(mut self, icon: Icon) -> Self { + self.alter_right_icon(icon); + self + } + pub fn with_target(mut self, target: AnchorTarget) -> Self { self.alter_target(target); self @@ -175,6 +193,18 @@ impl Anchor { self } + pub fn alter_left_icon(&mut self, icon: Icon) -> &mut Self { + self.left_icon.clear(); + self.left_icon.add(icon); + self + } + + pub fn alter_right_icon(&mut self, icon: Icon) -> &mut Self { + self.right_icon.clear(); + self.right_icon.add(icon); + self + } + pub fn alter_target(&mut self, target: AnchorTarget) -> &mut Self { self.target = target; self @@ -209,6 +239,14 @@ impl Anchor { &self.html } + pub fn left_icon(&self) -> &AnchorIcon { + &self.left_icon + } + + pub fn right_icon(&self) -> &AnchorIcon { + &self.right_icon + } + pub fn target(&self) -> &AnchorTarget { &self.target } diff --git a/pagetop/src/base/component/icon.rs b/pagetop/src/base/component/icon.rs new file mode 100644 index 00000000..1fb24120 --- /dev/null +++ b/pagetop/src/base/component/icon.rs @@ -0,0 +1,95 @@ +use crate::prelude::*; + +pub const ICON_COMPONENT: &str = "pagetop::component::icon"; + +pub struct Icon { + renderable: fn() -> bool, + weight : isize, + icon_name : String, +} + +impl ComponentTrait for Icon { + fn new() -> Self { + Icon { + renderable: render_always, + weight : 0, + icon_name : "question-circle-fill".to_owned(), + } + } + + fn handler(&self) -> &'static str { + ICON_COMPONENT + } + + fn is_renderable(&self) -> bool { + (self.renderable)() + } + + fn weight(&self) -> isize { + self.weight + } + + fn default_render(&self, context: &mut InContext) -> Markup { + context + .add_stylesheet(StyleSheet::with_source( + "/theme/icons/bootstrap-icons.css?ver=1.8.2" + )); + + let name = concat_string!("bi-", self.icon_name); + html! { i class=(name) {}; } + } + + fn as_ref_any(&self) -> &dyn AnyComponent { + self + } + + fn as_mut_any(&mut self) -> &mut dyn AnyComponent { + self + } +} + +impl Icon { + pub fn with(icon_name: &str) -> Self { + Icon::new().with_icon_name(icon_name) + } + + // Icon BUILDER. + + pub fn with_renderable(mut self, renderable: fn() -> bool) -> Self { + self.alter_renderable(renderable); + self + } + + pub fn with_weight(mut self, weight: isize) -> Self { + self.alter_weight(weight); + self + } + + pub fn with_icon_name(mut self, name: &str) -> Self { + self.alter_icon_name(name); + self + } + + // Icon ALTER. + + pub fn alter_renderable(&mut self, renderable: fn() -> bool) -> &mut Self { + self.renderable = renderable; + self + } + + pub fn alter_weight(&mut self, weight: isize) -> &mut Self { + self.weight = weight; + self + } + + pub fn alter_icon_name(&mut self, name: &str) -> &mut Self { + self.icon_name = name.to_owned(); + self + } + + // Icon GETTERS. + + pub fn icon_name(&self) -> &str { + &self.icon_name + } +} diff --git a/pagetop/src/base/module/demopage.rs b/pagetop/src/base/module/demopage.rs index f8753638..c3276124 100644 --- a/pagetop/src/base/module/demopage.rs +++ b/pagetop/src/base/module/demopage.rs @@ -58,17 +58,20 @@ fn hello_world() -> Container { "pagetop" => "PageTop" ])) })) - .add(Anchor::button("#", html! { ("Offered services") })) - .add(Anchor::button("#", html! { ("Get quote") })) - .add(Chunck::with(html! { - a class="btn-solid-lg" href="#services" { - "Offered services" - } - a class="quote" href="#contact" { - i class="fas fa-paper-plane" {} - "Get quote" - } - })) + .add(Anchor::button("#", + html! { + ("Offered services") + }).with_left_icon( + Icon::with("card-checklist") + ) + ) + .add(Anchor::button("#", + html! { + ("Get quote") + }).with_left_icon( + Icon::with("envelope-open-heart-fill") + ) + ) ) .add_column(grid::Column::new() .add(Image::image("/bootsier/images/demo-header.svg")) diff --git a/pagetop/src/core/component/bundle.rs b/pagetop/src/core/component/bundle.rs index 0477a4fd..f1042166 100644 --- a/pagetop/src/core/component/bundle.rs +++ b/pagetop/src/core/component/bundle.rs @@ -21,6 +21,10 @@ impl ComponentsBundle { self.0.push(Arc::new(RwLock::new(component))); } + pub fn clear(&mut self) { + self.0.clear(); + } + pub fn render(&self, context: &mut InContext) -> Markup { let mut components = self.0.clone(); components.sort_by_key(|c| c.read().unwrap().weight()); diff --git a/pagetop/static/theme/icons/bootstrap-icons.css b/pagetop/static/theme/icons/bootstrap-icons.css new file mode 100644 index 00000000..9a7d8ae2 --- /dev/null +++ b/pagetop/static/theme/icons/bootstrap-icons.css @@ -0,0 +1,1705 @@ +@font-face { + font-family: "bootstrap-icons"; + src: url("bootstrap-icons.woff2?ver=1.8.2") format("woff2"), + url("bootstrap-icons.woff?ver=1.8.2") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-display: block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-1::before { content: "\f2a5"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-1::before { content: "\f68a"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-1::before { content: "\f68d"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-1::before { content: "\f690"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-1::before { content: "\f695"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-1::before { content: "\f698"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-mortorboard-fill::before { content: "\f6a2"; } +.bi-mortorboard::before { content: "\f6a3"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-1::before { content: "\f6b6"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash-1::before { content: "\f6c2"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport-1::before { content: "\f6e0"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-ssd-fill::before { content: "\f6ed"; } +.bi-ssd::before { content: "\f6ee"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt-1::before { content: "\f759"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls-1::before { content: "\f769"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } diff --git a/pagetop/static/theme/icons/bootstrap-icons.woff b/pagetop/static/theme/icons/bootstrap-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..4cd66b71ad5f51be58843c52c66f78a8f7b89e47 GIT binary patch literal 137216 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Œ)MU&S(i~sr;ux&6XbkY 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

f4zyRkE1aA>Xa|PEa3QVZOr!r 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 G0001yd~9+6 literal 0 HcmV?d00001 From b3858887d419d81e41a44ba7eee28769ac09c5a9 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 7 Jun 2022 06:44:51 +0200 Subject: [PATCH 74/80] =?UTF-8?q?A=C3=B1ade=20las=20licencias=20del=20proy?= =?UTF-8?q?ecto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CREDITS.md | 1 + LICENSE-APACHE | 201 +++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 21 ++++ README.md | 48 ++++++++++ drust/Cargo.toml | 1 + pagetop-admin/Cargo.toml | 1 + pagetop-node/Cargo.toml | 1 + pagetop-user/Cargo.toml | 1 + pagetop/Cargo.toml | 2 +- 9 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md diff --git a/CREDITS.md b/CREDITS.md index 4254ed59..4965de82 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -14,6 +14,7 @@ incluidas en `src/app/banner` son: * [starwars.flf](http://www.figlet.org/fontdb_example.cgi?font=starwars.flf) por *Ryan Youck*. + # Icono El monstruo sonriente de Frankenstein es una divertida creación de diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000..263ddac1 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Manuel Cillero + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 00000000..cd8af3d6 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Manuel Cillero + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..9772e87c --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +[PageTop](https://suitepro.cillero.es/projects/pagetop/wiki) es un proyecto basado en el [lenguaje +de programación Rust](https://www.rust-lang.org/es/) que reúne algunos de los crates más estables y +populares en un único entorno para crear soluciones web modulares, extensibles y configurables. +Incluye **Drust**, un sistema de gestión de contenidos para crear sitios web dinámicos, rápidos y +seguros. + + +# Advertencia + +**PageTop** es un proyecto personal para aprender a programar con Rust y conocer su ecosistema. +Ahora mismo sólo se liberan versiones de desarrollo con pruebas de concepto. En este contexto la API +no tiene ninguna estabilidad y los cambios son constantes. Básicamente aún no hace nada. No puede +considerarse listo para usar en producción hasta que se libere la versión **0.1.0**. + + +# Estructura del código + +El repositorio se organiza en un *workspace* con los siguientes proyectos (*crates*): + +* [pagetop](pagetop/), es la librería esencial, reúne algunos de los crates más estables y + populares del ecosistema Rust para proporcionar APIs, patrones de desarrollo y buenas prácticas + para la creación avanzada de soluciones web. + +* [pagetop-admin](pagetop_admin/), habilita a otros módulos un entorno central para la + configuración de las aplicaciones. + +* [pagetop-user](pagetop_user/), para la gestión de usuarios, roles, permisos y sesiones en + aplicaciones desarrolladas con PageTop. + +* [pagetop-node](pagetop_node/), proporciona un entorno básico para crear contenidos y extenderlos + con funcionalidades básicas para, por ejemplo, crear un sitio básico con páginas, entradas de blog + y comentarios. + +* [drust](drust/), integra la librería y las extensiones anteriores de PageTop en un sistema de + gestión de contenidos para crear sitios web dinámicos, rápidos y seguros. + + +# Licencia + +Este proyecto tiene licencia, de hecho se puede aplicar cualquiera de las siguientes a tu elección: + +* Licencia Apache versión 2.0 + ([LICENSE-APACHE](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-APACHE) o + [http://www.apache.org/licenses/LICENSE-2.0]). + +* Licencia MIT + ([LICENSE-MIT](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-MIT) o + [http://opensource.org/licenses/MIT]). diff --git a/drust/Cargo.toml b/drust/Cargo.toml index 7a5412d5..4e06320a 100644 --- a/drust/Cargo.toml +++ b/drust/Cargo.toml @@ -11,6 +11,7 @@ description = """\ """ homepage = "https://suitepro.cillero.es/projects/drust" repository = "https://gitlab.com/manuelcillero/drust" +license = "Apache-2.0 or MIT" [dependencies.pagetop] path = "../pagetop" diff --git a/pagetop-admin/Cargo.toml b/pagetop-admin/Cargo.toml index 3dfc6e60..1f037317 100644 --- a/pagetop-admin/Cargo.toml +++ b/pagetop-admin/Cargo.toml @@ -11,6 +11,7 @@ description = """\ """ homepage = "https://suitepro.cillero.es/projects/pagetop" repository = "https://gitlab.com/manuelcillero/pagetop" +license = "Apache-2.0 or MIT" [dependencies] pagetop = { path = "../pagetop" } diff --git a/pagetop-node/Cargo.toml b/pagetop-node/Cargo.toml index 29857822..71412013 100644 --- a/pagetop-node/Cargo.toml +++ b/pagetop-node/Cargo.toml @@ -11,6 +11,7 @@ description = """\ """ homepage = "https://suitepro.cillero.es/projects/pagetop" repository = "https://gitlab.com/manuelcillero/pagetop" +license = "Apache-2.0 or MIT" [dependencies] pagetop = { path = "../pagetop" } diff --git a/pagetop-user/Cargo.toml b/pagetop-user/Cargo.toml index 3395241f..8781d7ff 100644 --- a/pagetop-user/Cargo.toml +++ b/pagetop-user/Cargo.toml @@ -11,6 +11,7 @@ description = """\ """ homepage = "https://suitepro.cillero.es/projects/pagetop" repository = "https://gitlab.com/manuelcillero/pagetop" +license = "Apache-2.0 or MIT" [dependencies] pagetop = { path = "../pagetop" } diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 6bde05af..ba9a6726 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -12,7 +12,7 @@ description = """\ """ homepage = "https://suitepro.cillero.es/projects/pagetop" repository = "https://gitlab.com/manuelcillero/pagetop" -license = "MIT" +license = "Apache-2.0 or MIT" keywords = [ "web", "cms", "framework", "frontend", "ssr" From a6c6d3387acfa003969ee437d30a8f26ef3efd39 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 7 Jun 2022 05:07:20 +0000 Subject: [PATCH 75/80] =?UTF-8?q?A=C3=B1ade=20licencia=20Apache=20versi?= =?UTF-8?q?=C3=B3n=202.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ea237b29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Manuel Cillero + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 45e43bfe70afb908703baee0de1545c77e4439e9 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 7 Jun 2022 05:08:36 +0000 Subject: [PATCH 76/80] =?UTF-8?q?Revert=20"A=C3=B1ade=20licencia=20Apache?= =?UTF-8?q?=20versi=C3=B3n=202.0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a6c6d3387acfa003969ee437d30a8f26ef3efd39 --- LICENSE | 201 -------------------------------------------------------- 1 file changed, 201 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ea237b29..00000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2022 Manuel Cillero - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. From 091bbe16ba93cfa0a95f0384c56a370a6cb5cd48 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 23 Jun 2022 00:18:40 +0200 Subject: [PATCH 77/80] =?UTF-8?q?Modifica=20README=20en=20espa=C3=B1ol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 48 ------------------------------------------------ README_es.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 48 deletions(-) delete mode 100644 README.md create mode 100644 README_es.md diff --git a/README.md b/README.md deleted file mode 100644 index 9772e87c..00000000 --- a/README.md +++ /dev/null @@ -1,48 +0,0 @@ -[PageTop](https://suitepro.cillero.es/projects/pagetop/wiki) es un proyecto basado en el [lenguaje -de programación Rust](https://www.rust-lang.org/es/) que reúne algunos de los crates más estables y -populares en un único entorno para crear soluciones web modulares, extensibles y configurables. -Incluye **Drust**, un sistema de gestión de contenidos para crear sitios web dinámicos, rápidos y -seguros. - - -# Advertencia - -**PageTop** es un proyecto personal para aprender a programar con Rust y conocer su ecosistema. -Ahora mismo sólo se liberan versiones de desarrollo con pruebas de concepto. En este contexto la API -no tiene ninguna estabilidad y los cambios son constantes. Básicamente aún no hace nada. No puede -considerarse listo para usar en producción hasta que se libere la versión **0.1.0**. - - -# Estructura del código - -El repositorio se organiza en un *workspace* con los siguientes proyectos (*crates*): - -* [pagetop](pagetop/), es la librería esencial, reúne algunos de los crates más estables y - populares del ecosistema Rust para proporcionar APIs, patrones de desarrollo y buenas prácticas - para la creación avanzada de soluciones web. - -* [pagetop-admin](pagetop_admin/), habilita a otros módulos un entorno central para la - configuración de las aplicaciones. - -* [pagetop-user](pagetop_user/), para la gestión de usuarios, roles, permisos y sesiones en - aplicaciones desarrolladas con PageTop. - -* [pagetop-node](pagetop_node/), proporciona un entorno básico para crear contenidos y extenderlos - con funcionalidades básicas para, por ejemplo, crear un sitio básico con páginas, entradas de blog - y comentarios. - -* [drust](drust/), integra la librería y las extensiones anteriores de PageTop en un sistema de - gestión de contenidos para crear sitios web dinámicos, rápidos y seguros. - - -# Licencia - -Este proyecto tiene licencia, de hecho se puede aplicar cualquiera de las siguientes a tu elección: - -* Licencia Apache versión 2.0 - ([LICENSE-APACHE](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-APACHE) o - [http://www.apache.org/licenses/LICENSE-2.0]). - -* Licencia MIT - ([LICENSE-MIT](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-MIT) o - [http://opensource.org/licenses/MIT]). diff --git a/README_es.md b/README_es.md new file mode 100644 index 00000000..cada225c --- /dev/null +++ b/README_es.md @@ -0,0 +1,48 @@ +**PageTop** es un entorno de desarrollo basado en [Rust](https://www.rust-lang.org/es/) que reúne +algunos de los crates más estables y populares para crear soluciones web modulares, extensibles y +configurables. + +Incluye **Drust**, un sistema de gestión de contenidos basado en PageTop que permite crear, editar y +mantener sitios web dinámicos, rápidos y seguros. + + +# Advertencia + +**PageTop** es un proyecto personal para aprender Rust y conocer su ecosistema. Ahora mismo sólo se +liberan versiones de desarrollo. En este contexto la API no tiene ninguna estabilidad y los cambios +son constantes. No puede considerarse listo para probar hasta que se libere la versión **0.1.0**. + + +# Estructura del código + +El repositorio se organiza en un *workspace* con los siguientes subproyectos: + +* [pagetop](pagetop/), es la librería esencial construida con *crates* estables y muy conocidos del + ecosistema Rust para proporcionar APIs, patrones de desarrollo y buenas prácticas para la creación + avanzada de soluciones web SSR (*Server-Side Rendering*). + +* [pagetop-admin](pagetop_admin/), módulo que proporciona a otros módulos un lugar común donde + presentar a los administradores sus opciones de configuración. + +* [pagetop-user](pagetop_user/), módulo para añadir una gestión de usuarios, roles, permisos y + sesiones en aplicaciones desarrolladas con PageTop. + +* [pagetop-node](pagetop_node/), módulo para crear y extender los tipos de contenido que puede + gestionar una solución web de propósito general o personalizado. + +* [drust](drust/), es una aplicación humildemente inspirada en [Drupal](https://www.drupal.org) que + proporciona un CMS (*Content Management System*) o sistema de gestión de contenidos para construir + sitios web administrados y configurables. + + +# Licencia + +Este proyecto tiene licencia, de hecho se puede aplicar cualquiera de las siguientes a tu elección: + +* Licencia Apache versión 2.0 + ([LICENSE-APACHE](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-APACHE) o + [http://www.apache.org/licenses/LICENSE-2.0]). + +* Licencia MIT + ([LICENSE-MIT](https://gitlab.com/manuelcillero/pagetop/-/blob/main/LICENSE-MIT) o + [http://opensource.org/licenses/MIT]). From 0bad86cf686d8cc04f7905e0db01fec77abd7f85 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Thu, 23 Jun 2022 00:20:44 +0200 Subject: [PATCH 78/80] =?UTF-8?q?Corrige=20presentaci=C3=B3n=20de=20README?= =?UTF-8?q?=20en=20GitHub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README_es.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README_es.md => README.md (100%) diff --git a/README_es.md b/README.md similarity index 100% rename from README_es.md rename to README.md From 7c30a90c76a4f5624b0d0c4f49ceb6e6108eca19 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 28 Jun 2022 23:52:51 +0200 Subject: [PATCH 79/80] =?UTF-8?q?Actualiza=20SeaORM=20a=20la=20versi=C3=B3?= =?UTF-8?q?n=200.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ pagetop/Cargo.toml | 18 ++++++++---------- pagetop/src/db.rs | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cada225c..9f8d5024 100644 --- a/README.md +++ b/README.md @@ -24,15 +24,15 @@ El repositorio se organiza en un *workspace* con los siguientes subproyectos: * [pagetop-admin](pagetop_admin/), módulo que proporciona a otros módulos un lugar común donde presentar a los administradores sus opciones de configuración. -* [pagetop-user](pagetop_user/), módulo para añadir una gestión de usuarios, roles, permisos y - sesiones en aplicaciones desarrolladas con PageTop. +* [pagetop-user](pagetop_user/), módulo para añadir gestión de usuarios, roles, permisos y sesiones + en aplicaciones desarrolladas con PageTop. -* [pagetop-node](pagetop_node/), módulo para crear y extender los tipos de contenido que puede - gestionar una solución web de propósito general o personalizado. +* [pagetop-node](pagetop_node/), módulo para crear, extender o personalizar los tipos de contenido + que puede administrar un sitio web. -* [drust](drust/), es una aplicación humildemente inspirada en [Drupal](https://www.drupal.org) que +* [drust](drust/) es una aplicación inspirada modestamente en [Drupal](https://www.drupal.org) que proporciona un CMS (*Content Management System*) o sistema de gestión de contenidos para construir - sitios web administrados y configurables. + sitios web dinámicos, administrados y configurables. # Licencia diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index ba9a6726..15a979c3 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -26,14 +26,14 @@ concat-string = "1.0.1" doc-comment = "0.3.3" figlet-rs = "0.1.3" futures = "0.3.21" -once_cell = "1.10.0" +once_cell = "1.12.0" substring = "1.4.5" term_size = "0.3.2" url = "2.2.2" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } -tracing = "0.1.34" +tracing = "0.1.35" tracing-appender = "0.2.2" tracing-subscriber = { version = "0.3.11", features = ["json", "env-filter"] } tracing-unwrap = { version = "0.9.2", default-features = false } @@ -52,22 +52,20 @@ sycamore = { version = "0.7.1", features = ["ssr"] } serde = { version = "1.0", features = ["derive"] } [dependencies.sea-orm] -version = "0.7.1" +version = "0.8.0" features = ["debug-print", "macros", "runtime-async-std-native-tls"] default-features = false optional = true -[dependencies.sea-schema] -version = "0.7.1" -features = ["debug-print", "migration"] -default-features = false +[dependencies.sea-orm-migration] +version = "0.8.3" optional = true [features] default = [] -mysql = ["sea-orm", "sea-schema", "sea-orm/sqlx-mysql"] -postgres = ["sea-orm", "sea-schema", "sea-orm/sqlx-postgres"] -sqlite = ["sea-orm", "sea-schema", "sea-orm/sqlx-sqlite"] +mysql = ["sea-orm", "sea-orm-migration", "sea-orm/sqlx-mysql"] +postgres = ["sea-orm", "sea-orm-migration", "sea-orm/sqlx-postgres"] +sqlite = ["sea-orm", "sea-orm-migration", "sea-orm/sqlx-sqlite"] [build-dependencies] actix-web-static-files = "3.0.5" diff --git a/pagetop/src/db.rs b/pagetop/src/db.rs index d350043e..3c25c0dc 100644 --- a/pagetop/src/db.rs +++ b/pagetop/src/db.rs @@ -2,7 +2,7 @@ pub use url::Url as DbUri; pub use sea_orm::{DatabaseConnection as DbConn, ExecResult, QueryResult}; -pub use sea_schema::migration::prelude::*; +pub use sea_orm_migration::prelude::*; pub type MigrationItem = Box; From 7be5520f5cc17161368e246dbb2cfe09b263be2d Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 28 Jun 2022 23:53:25 +0200 Subject: [PATCH 80/80] =?UTF-8?q?Libera=20la=20versi=C3=B3n=20de=20desarro?= =?UTF-8?q?llo=200.0.16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 15a979c3..434fe9a0 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pagetop" -version = "0.0.15" +version = "0.0.16" edition = "2021" authors = [

Ua;3k(y1@iWd^?TBH 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