🎨 [pagetop] Mejora gestión de URLs según contexto

This commit is contained in:
Manuel Cillero 2025-12-03 06:41:52 +01:00
parent 4944af073f
commit 51e18cf5ee
6 changed files with 32 additions and 28 deletions

View file

@ -10,10 +10,7 @@ impl Extension for SuperMenu {
} }
fn initialize(&self) { fn initialize(&self) {
let home_path = |cx: &Context| match cx.langid().language.as_str() { let home_path = |cx: &Context| join!("/lang/", cx.langid().language.as_str()).into();
"en" => "/en",
_ => "/",
};
let navbar_menu = Navbar::brand_left(navbar::Brand::new().with_path(Some(home_path))) let navbar_menu = Navbar::brand_left(navbar::Brand::new().with_path(Some(home_path)))
.with_expand(BreakPoint::LG) .with_expand(BreakPoint::LG)
@ -25,7 +22,7 @@ impl Extension for SuperMenu {
)) ))
.add_item(nav::Item::link_blank( .add_item(nav::Item::link_blank(
L10n::l("sample_menus_item_blank"), L10n::l("sample_menus_item_blank"),
|_| "https://docs.rs/pagetop", |_| "https://docs.rs/pagetop".into(),
)) ))
.add_item(nav::Item::dropdown( .add_item(nav::Item::dropdown(
Dropdown::new() Dropdown::new()
@ -33,28 +30,28 @@ impl Extension for SuperMenu {
.add_item(dropdown::Item::header(L10n::l("sample_menus_dev_header"))) .add_item(dropdown::Item::header(L10n::l("sample_menus_dev_header")))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_dev_getting_started"), L10n::l("sample_menus_dev_getting_started"),
|_| "/dev/getting-started", |_| "/dev/getting-started".into(),
)) ))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_dev_guides"), L10n::l("sample_menus_dev_guides"),
|_| "/dev/guides", |_| "/dev/guides".into(),
)) ))
.add_item(dropdown::Item::link_blank( .add_item(dropdown::Item::link_blank(
L10n::l("sample_menus_dev_forum"), L10n::l("sample_menus_dev_forum"),
|_| "https://forum.example.dev", |_| "https://forum.example.dev".into(),
)) ))
.add_item(dropdown::Item::divider()) .add_item(dropdown::Item::divider())
.add_item(dropdown::Item::header(L10n::l("sample_menus_sdk_header"))) .add_item(dropdown::Item::header(L10n::l("sample_menus_sdk_header")))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_sdk_rust"), L10n::l("sample_menus_sdk_rust"),
|_| "/dev/sdks/rust", |_| "/dev/sdks/rust".into(),
)) ))
.add_item(dropdown::Item::link(L10n::l("sample_menus_sdk_js"), |_| { .add_item(dropdown::Item::link(L10n::l("sample_menus_sdk_js"), |_| {
"/dev/sdks/js" "/dev/sdks/js".into()
})) }))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_sdk_python"), L10n::l("sample_menus_sdk_python"),
|_| "/dev/sdks/python", |_| "/dev/sdks/python".into(),
)) ))
.add_item(dropdown::Item::divider()) .add_item(dropdown::Item::divider())
.add_item(dropdown::Item::header(L10n::l( .add_item(dropdown::Item::header(L10n::l(
@ -62,22 +59,22 @@ impl Extension for SuperMenu {
))) )))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_plugin_auth"), L10n::l("sample_menus_plugin_auth"),
|_| "/dev/sdks/rust/plugins/auth", |_| "/dev/sdks/rust/plugins/auth".into(),
)) ))
.add_item(dropdown::Item::link( .add_item(dropdown::Item::link(
L10n::l("sample_menus_plugin_cache"), L10n::l("sample_menus_plugin_cache"),
|_| "/dev/sdks/rust/plugins/cache", |_| "/dev/sdks/rust/plugins/cache".into(),
)) ))
.add_item(dropdown::Item::divider()) .add_item(dropdown::Item::divider())
.add_item(dropdown::Item::label(L10n::l("sample_menus_item_label"))) .add_item(dropdown::Item::label(L10n::l("sample_menus_item_label")))
.add_item(dropdown::Item::link_disabled( .add_item(dropdown::Item::link_disabled(
L10n::l("sample_menus_item_disabled"), L10n::l("sample_menus_item_disabled"),
|_| "#", |_| "#".into(),
)), )),
)) ))
.add_item(nav::Item::link_disabled( .add_item(nav::Item::link_disabled(
L10n::l("sample_menus_item_disabled"), L10n::l("sample_menus_item_disabled"),
|_| "#", |_| "#".into(),
)), )),
)) ))
.add_item(navbar::Item::nav( .add_item(navbar::Item::nav(
@ -88,10 +85,10 @@ impl Extension for SuperMenu {
) )
.add_item(nav::Item::link( .add_item(nav::Item::link(
L10n::l("sample_menus_item_sign_up"), L10n::l("sample_menus_item_sign_up"),
|_| "/auth/sign-up", |_| "/auth/sign-up".into(),
)) ))
.add_item(nav::Item::link(L10n::l("sample_menus_item_login"), |_| { .add_item(nav::Item::link(L10n::l("sample_menus_item_login"), |_| {
"/auth/login" "/auth/login".into()
})), })),
)); ));

View file

@ -81,7 +81,7 @@ impl Component for Item {
} => { } => {
let path = path(cx); let path = path(cx);
let current_path = cx.request().map(|request| request.path()); let current_path = cx.request().map(|request| request.path());
let is_current = !*disabled && (current_path == Some(path)); let is_current = !*disabled && (current_path == Some(&path));
let mut classes = "dropdown-item".to_string(); let mut classes = "dropdown-item".to_string();
if is_current { if is_current {

View file

@ -115,7 +115,7 @@ impl Component for Item {
} => { } => {
let path = path(cx); let path = path(cx);
let current_path = cx.request().map(|request| request.path()); let current_path = cx.request().map(|request| request.path());
let is_current = !*disabled && (current_path == Some(path)); let is_current = !*disabled && (current_path == Some(&path));
let mut classes = "nav-link".to_string(); let mut classes = "nav-link".to_string();
if is_current { if is_current {

View file

@ -23,7 +23,7 @@ pub struct Brand {
/// Devuelve el eslogan de la marca. /// Devuelve el eslogan de la marca.
slogan: L10n, slogan: L10n,
/// Devuelve la función que resuelve la URL asociada a la marca (si existe). /// Devuelve la función que resuelve la URL asociada a la marca (si existe).
#[default(_code = "Some(|_| \"/\")")] #[default(_code = "Some(|_| \"/\".into())")]
path: Option<FnPathByContext>, path: Option<FnPathByContext>,
} }

View file

@ -91,13 +91,14 @@ pub struct Intro {
} }
impl Default for Intro { impl Default for Intro {
#[rustfmt::skip]
fn default() -> Self { fn default() -> Self {
const BUTTON_LINK: &str = "https://pagetop.cillero.es";
Intro { Intro {
title : L10n::l("intro_default_title"), title: L10n::l("intro_default_title"),
slogan : L10n::l("intro_default_slogan").with_arg("app", &global::SETTINGS.app.name), slogan: L10n::l("intro_default_slogan").with_arg("app", &global::SETTINGS.app.name),
button : Some((L10n::l("intro_default_button"), |_| "https://pagetop.cillero.es")), button: Some((L10n::l("intro_default_button"), |_| BUTTON_LINK.into())),
opening : IntroOpening::default(), opening: IntroOpening::default(),
children: Children::default(), children: Children::default(),
} }
} }

View file

@ -1,5 +1,7 @@
//! API para construir nuevos componentes. //! API para construir nuevos componentes.
use std::borrow::Cow;
mod definition; mod definition;
pub use definition::{Component, ComponentRender}; pub use definition::{Component, ComponentRender};
@ -66,6 +68,10 @@ pub type FnIsRenderable = fn(cx: &Context) -> bool;
/// Alias de función (*callback*) para **resolver una URL** según el contexto de renderizado. /// Alias de función (*callback*) para **resolver una URL** según el contexto de renderizado.
/// ///
/// Se usa para generar enlaces dinámicos en función del contexto (petición, idioma, etc.). Debe /// Se usa para generar enlaces dinámicos en función del contexto (petición, idioma, etc.). El
/// devolver una referencia válida durante el renderizado. /// resultado se devuelve como [`Cow<'static, str>`](std::borrow::Cow), lo que permite:
pub type FnPathByContext = fn(cx: &Context) -> &str; ///
/// - Usar rutas estáticas sin asignaciones adicionales (`"/path".into()`).
/// - Construir rutas dinámicas en tiempo de ejecución (`format!(...).into()`), por ejemplo, en
/// función de parámetros almacenados en [`Context`].
pub type FnPathByContext = fn(cx: &Context) -> Cow<'static, str>;