diff --git a/src/base/extension/welcome.rs b/src/base/extension/welcome.rs index e2a7712..5c6fec5 100644 --- a/src/base/extension/welcome.rs +++ b/src/base/extension/welcome.rs @@ -25,55 +25,30 @@ async fn homepage(request: HttpRequest) -> ResultPage { let app = &global::SETTINGS.app.name; Page::new(request) - .with_theme("basic") - .with_layout("intro") + .with_theme("Basic") + .with_layout("PageTopIntro") .with_title(L10n::l("welcome_title")) .with_description(L10n::l("welcome_intro").with_arg("app", app)) - .with_param("intro_button_text", L10n::l("welcome_powered")) - .with_param("intro_button_link", "https://pagetop.cillero.es".to_string()) - .with_assets(AssetsOp::AddJavaScript(JavaScript::on_load_async("welcome-js", |cx| - util::indoc!(r#" - try { - const resp = await fetch("https://crates.io/api/v1/crates/pagetop"); - const data = await resp.json(); - const date = new Date(data.versions[0].created_at); - const formatted = date.toLocaleDateString("LANGID", { year: "numeric", month: "2-digit", day: "2-digit" }); - document.getElementById("welcome-release").src = `https://img.shields.io/badge/Release%20date-${encodeURIComponent(formatted)}-blue?label=LABEL&style=for-the-badge`; - document.getElementById("welcome-badges").style.display = "block"; - } catch (e) { - console.error("Failed to fetch release date from crates.io:", e); - } - "#) - .replace("LANGID", cx.langid().to_string().as_str()) - .replace("LABEL", L10n::l("welcome_release_label").using(cx).as_str()) - .to_string(), - ))) - .add_component(Html::with(|cx| html! { - p { (L10n::l("welcome_text1").using(cx)) } - div id="welcome-badges" style="display: none; margin-bottom: 1.1rem;" { - img - src="https://img.shields.io/crates/v/pagetop.svg?label=PageTop&style=for-the-badge" - alt=[L10n::l("welcome_pagetop_label").lookup(cx)] {} (" ") - img - id="welcome-release" - alt=[L10n::l("welcome_release_label").lookup(cx)] {} (" ") - img - src=(format!( - "https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label={}&style=for-the-badge", - L10n::l("welcome_license_label").lookup(cx).unwrap_or_default() - )) - alt=[L10n::l("welcome_license_label").lookup(cx)] {} - } - p { (L10n::l("welcome_text2").using(cx)) } - })) + .with_param("intro_button_txt", L10n::l("welcome_powered")) + .with_param("intro_button_lnk", "https://pagetop.cillero.es".to_string()) .add_component( Block::new() - .with_title(L10n::l("welcome_notice_title")) - .add_component(Html::with(move |cx| html! { - p { (L10n::l("welcome_notice_1").using(cx)) } - p { (L10n::l("welcome_notice_2").using(cx)) } - p { (L10n::l("welcome_notice_3").using(cx)) } - p { (L10n::l("welcome_notice_4").with_arg("app", app).using(cx)) } + .with_title(L10n::l("welcome_status_title")) + .add_component(Html::with(move |cx| { + html! { + p { (L10n::l("welcome_status_1").using(cx)) } + p { (L10n::l("welcome_status_2").using(cx)) } + } + })), + ) + .add_component( + Block::new() + .with_title(L10n::l("welcome_support_title")) + .add_component(Html::with(move |cx| { + html! { + p { (L10n::l("welcome_support_1").using(cx)) } + p { (L10n::l("welcome_support_2").with_arg("app", app).using(cx)) } + } })), ) .render() diff --git a/src/base/theme/basic.rs b/src/base/theme/basic.rs index e652548..2f49274 100644 --- a/src/base/theme/basic.rs +++ b/src/base/theme/basic.rs @@ -1,8 +1,33 @@ -//! Es el tema básico que incluye PageTop por defecto. - +/// Es el tema básico que incluye PageTop por defecto. use crate::prelude::*; /// Tema básico por defecto. +/// +/// Ofrece las siguientes composiciones (*layouts*): +/// +/// - **Composición predeterminada** +/// - Renderizado genérico con +/// [`ThemePage::render_body()`](crate::core::theme::ThemePage::render_body) usando las regiones +/// predefinidas en [`page_regions()`](crate::core::theme::Theme::page_regions). +/// +/// - **`Intro`** +/// - Página de entrada con cabecera visual, título y descripción y un botón opcional de llamada a +/// la acción. Ideal para una página de inicio o bienvenida en el contexto de PageTop. +/// - **Regiones:** `content` (se renderiza dentro de `.intro-content__body`). +/// - **Parámetros:** +/// - `intro_button_txt` (`L10n`) – Texto del botón. +/// - `intro_button_lnk` (`Option`) – URL del botón; si no se indica, el botón no se +/// muestra. +/// +/// - **`PageTopIntro`** +/// - Variante de `Intro` con textos predefinidos sobre PageTop al inicio del contenido. Añade una +/// banda de *badges* con la versión de [PageTop en crates.io](https://crates.io/crates/pagetop) +/// más la fecha de la última versión publicada y la licencia de uso. +/// - **Regiones:** `content` (igual que `Intro`). +/// - **Parámetros:** los mismos que `Intro`. +/// +/// **Nota:** si no se especifica `layout` o el valor no coincide con ninguno de los anteriores, se +/// aplica la composición predeterminada. pub struct Basic; impl Extension for Basic { @@ -14,14 +39,16 @@ impl Extension for Basic { impl Theme for Basic { fn render_page_body(&self, page: &mut Page) -> Markup { match page.layout() { - "intro" => render_intro(page), + "Intro" => render_intro(page), + "PageTopIntro" => render_pagetop_intro(page), _ => ::render_body(self, page, self.page_regions()), } } fn after_render_page_body(&self, page: &mut Page) { let styles = match page.layout() { - "intro" => "/css/intro.css", + "Intro" => "/css/intro.css", + "PageTopIntro" => "/css/intro.css", _ => "/css/basic.css", }; page.alter_assets(AssetsOp::AddStyleSheet( @@ -41,8 +68,8 @@ fn render_intro(page: &mut Page) -> Markup { let title = page.title().unwrap_or_default(); let intro = page.description().unwrap_or_default(); - let intro_button_text: L10n = page.param_or_default("intro_button_text"); - let intro_button_link: Option<&String> = page.param("intro_button_link"); + let intro_button_txt: L10n = page.param_or_default("intro_button_txt"); + let intro_button_lnk: Option<&String> = page.param("intro_button_lnk"); html! { body id=[page.body_id().get()] class=[page.body_classes().get()] { @@ -74,17 +101,17 @@ fn render_intro(page: &mut Page) -> Markup { } main class="intro-content" { section class="intro-content__body" { - @if intro_button_link.is_some() { + @if intro_button_lnk.is_some() { div class="intro-button" { a class="intro-button__link" - href=[intro_button_link] + href=[intro_button_lnk] target="_blank" rel="noreferrer" { span {} span {} span {} div class="intro-button__text" { - (intro_button_text.using(page)) + (intro_button_txt.using(page)) } } } @@ -119,3 +146,43 @@ fn render_intro(page: &mut Page) -> Markup { } } } + +fn render_pagetop_intro(page: &mut Page) -> Markup { + page.alter_assets(AssetsOp::AddJavaScript(JavaScript::on_load_async("intro-js", |cx| + util::indoc!(r#" + try { + const resp = await fetch("https://crates.io/api/v1/crates/pagetop"); + const data = await resp.json(); + const date = new Date(data.versions[0].created_at); + const formatted = date.toLocaleDateString("LANGID", { year: "numeric", month: "2-digit", day: "2-digit" }); + document.getElementById("intro-release").src = `https://img.shields.io/badge/Release%20date-${encodeURIComponent(formatted)}-blue?label=LABEL&style=for-the-badge`; + document.getElementById("intro-badges").style.display = "block"; + } catch (e) { + console.error("Failed to fetch release date from crates.io:", e); + } + "#) + .replace("LANGID", cx.langid().to_string().as_str()) + .replace("LABEL", L10n::l("intro_release_label").using(cx).as_str()) + .to_string(), + ))) + .alter_child_in("content", ChildOp::Prepend(Child::with(Html::with(|cx| html! { + p { (L10n::l("intro_text1").using(cx)) } + div id="intro-badges" style="display: none; margin-bottom: 1.1rem;" { + img + src="https://img.shields.io/crates/v/pagetop.svg?label=PageTop&style=for-the-badge" + alt=[L10n::l("intro_pagetop_label").lookup(cx)] {} (" ") + img + id="intro-release" + alt=[L10n::l("intro_release_label").lookup(cx)] {} (" ") + img + src=(format!( + "https://img.shields.io/badge/license-MIT%2FApache-blue.svg?label={}&style=for-the-badge", + L10n::l("intro_license_label").lookup(cx).unwrap_or_default() + )) + alt=[L10n::l("intro_license_label").lookup(cx)] {} + } + p { (L10n::l("intro_text2").using(cx)) } + })))); + + render_intro(page) +} diff --git a/src/core/theme/definition.rs b/src/core/theme/definition.rs index a4faf0b..38a0bfc 100644 --- a/src/core/theme/definition.rs +++ b/src/core/theme/definition.rs @@ -125,18 +125,18 @@ pub trait Theme: Extension + ThemePage + Send + Sync { /// Declaración ordenada de las regiones disponibles en la página. /// - /// Devuelve una **lista estática** de pares `(Region, L10n)` que se usará para renderizar en el - /// orden indicado todas las regiones que componen una página. + /// Devuelve una **lista estática** de pares `(Region, L10n)` que se usará para renderizar todas + /// las regiones que componen una página en el orden indicado . /// - /// Requisitos y recomendaciones: + /// Si un tema necesita un conjunto distinto de regiones, se puede **sobrescribir** este método + /// con los siguientes requisitos y recomendaciones: /// /// - Los identificadores deben ser **estables** (p. ej. `"sidebar-left"`, `"content"`). /// - La región `"content"` es **obligatoria**. Se puede usar [`Region::default()`] para /// declararla. /// - La etiqueta `L10n` se evalúa con el idioma activo de la página. /// - /// Si tu tema define un conjunto distinto, se puede **sobrescribir** este método. Por defecto - /// devuelve: + /// Por defecto devuelve: /// /// - `"header"`: cabecera. /// - `"content"`: contenido principal (**obligatoria**). diff --git a/src/locale/en-US/base.ftl b/src/locale/en-US/base.ftl index 7a9701d..16b1a3e 100644 --- a/src/locale/en-US/base.ftl +++ b/src/locale/en-US/base.ftl @@ -1,4 +1,11 @@ # Basic theme, intro layout. +intro_pagetop_label = PageTop version on Crates.io +intro_release_label = Release date +intro_license_label = License + +intro_text1 = PageTop is an opinionated Rust web development framework designed to build modular, extensible, and configurable web solutions. +intro_text2 = PageTop brings back the essence of the classic web, renders on the server (SSR) and uses HTML-first components, CSS and JavaScript, with the performance and security of Rust. + intro_code = Code intro_have_fun = Coding is creating diff --git a/src/locale/en-US/welcome.ftl b/src/locale/en-US/welcome.ftl index 0a227f1..20faf96 100644 --- a/src/locale/en-US/welcome.ftl +++ b/src/locale/en-US/welcome.ftl @@ -7,15 +7,10 @@ welcome_title = Hello, world! welcome_intro = Discover⚡{ $app } welcome_powered = A web solution powered by PageTop -welcome_pagetop_label = PageTop version on Crates.io -welcome_release_label = Release date -welcome_license_label = License +welcome_status_title = Status +welcome_status_1 = If you can see this page, it means the PageTop server is running correctly, but the application is not fully configured. This may be due to routine maintenance or a temporary issue. +welcome_status_2 = If the issue persists, please contact the system administrator. -welcome_text1 = PageTop is a Rust-based web development framework designed to build modular, extensible, and configurable web solutions. -welcome_text2 = PageTop brings back the essence of the classic web, renders on the server (SSR) and uses HTML-first components, CSS and JavaScript, with the performance and security of Rust. - -welcome_notice_title = Notice -welcome_notice_1 = If you can see this page, the PageTop server is running correctly, but the application is not fully configured. This may be due to routine maintenance or a temporary issue. -welcome_notice_2 = If the issue persists, please contact the system administrator. -welcome_notice_3 = To report issues with the PageTop framework, use SoloGit. Before opening a new issue, review the existing ones to avoid duplicates. -welcome_notice_4 = For issues specific to the application ({ $app }), please use its official repository or support channel. +welcome_support_title = Support +welcome_support_1 = To report issues with the PageTop framework, use SoloGit. Remember, before opening a new issue, review the existing ones to avoid duplicates. +welcome_support_2 = For issues specific to the application ({ $app }), please use its official repository or support channel. diff --git a/src/locale/es-ES/base.ftl b/src/locale/es-ES/base.ftl index 99f6c7e..fee21a9 100644 --- a/src/locale/es-ES/base.ftl +++ b/src/locale/es-ES/base.ftl @@ -1,4 +1,11 @@ # Basic theme, intro layout. +intro_pagetop_label = Versión de PageTop en Crates.io +intro_release_label = Lanzamiento +intro_license_label = Licencia + +intro_text1 = PageTop es un entorno de desarrollo web basado en Rust, pensado para construir soluciones web modulares, extensibles y configurables. +intro_text2 = PageTop reivindica la esencia de la web clásica, renderiza en el servidor (SSR) utilizando componentes HTML-first, CSS y JavaScript, con el rendimiento y la seguridad de Rust. + intro_code = Código intro_have_fun = Programar es crear diff --git a/src/locale/es-ES/welcome.ftl b/src/locale/es-ES/welcome.ftl index b98d919..13330db 100644 --- a/src/locale/es-ES/welcome.ftl +++ b/src/locale/es-ES/welcome.ftl @@ -7,15 +7,10 @@ welcome_title = ¡Hola, mundo! welcome_intro = Descubre⚡{ $app } welcome_powered = Una solución web creada con PageTop -welcome_pagetop_label = Versión de PageTop en Crates.io -welcome_release_label = Lanzamiento -welcome_license_label = Licencia +welcome_status_title = Estado +welcome_status_1 = Si puedes ver esta página, es porque el servidor de PageTop está funcionando correctamente, pero la aplicación no está completamente configurada. Esto puede deberse a tareas de mantenimiento o a una incidencia temporal. +welcome_status_2 = Si el problema persiste, por favor, contacta con el administrador del sistema. -welcome_text1 = PageTop es un entorno de desarrollo web basado en Rust, pensado para construir soluciones web modulares, extensibles y configurables. -welcome_text2 = PageTop reivindica la esencia de la web clásica, renderiza en el servidor (SSR) utilizando componentes HTML-first, CSS y JavaScript, con el rendimiento y la seguridad de Rust. - -welcome_notice_title = Aviso -welcome_notice_1 = Si puedes ver esta página, el servidor de PageTop está funcionando correctamente, pero la aplicación no está completamente configurada. Esto puede deberse a tareas de mantenimiento o a una incidencia temporal. -welcome_notice_2 = Si el problema persiste, por favor, contacta con el administrador del sistema. -welcome_notice_3 = Para comunicar incidencias del propio entorno PageTop, utiliza SoloGit. Antes de abrir una nueva incidencia, revisa las existentes para evitar duplicados. -welcome_notice_4 = Para fallos específicos de la aplicación ({ $app }), utiliza su repositorio oficial o su canal de soporte. +welcome_support_title = Soporte +welcome_support_1 = Para comunicar incidencias del propio entorno PageTop, utiliza SoloGit. Recuerda, antes de abrir una nueva incidencia, revisa las existentes para evitar duplicados. +welcome_support_2 = Para fallos específicos de la aplicación ({ $app }), utiliza su repositorio oficial o su canal de soporte. diff --git a/static/css/intro.css b/static/css/intro.css index 19fa9f1..39c9d6a 100644 --- a/static/css/intro.css +++ b/static/css/intro.css @@ -7,9 +7,9 @@ --color: #1a202c; --color-gray: #e4e4e7; --color-link: #1e4eae; - --color-block-1: #fecaca; - --color-block-2: #e6a9e2; - --color-block-3: #b689ff; + --color-block-1: #b689ff; + --color-block-2: #fecaca; + --color-block-3: #e6a9e2; --color-block-4: #ffedca; --color-block-5: #ffffff; --focus-outline: 2px solid var(--color-link);