From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH datacenter-manager] ui: search box: close if user navigated to an entry
Date: Fri, 5 Sep 2025 09:29:20 +0200 [thread overview]
Message-ID: <20250905072928.782706-1-d.csapak@proxmox.com> (raw)
either by clicking or using the keyboard. For this we need to add a new
'on_navigate' callback in the ResourceTree that triggers when the user
navigated away.
While at it, refactor the navigation callbacks into the update method.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/src/widget/resource_tree.rs | 66 ++++++++++++++++++----------------
ui/src/widget/search_box.rs | 6 ++++
2 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/ui/src/widget/resource_tree.rs b/ui/src/widget/resource_tree.rs
index aefcaf6..708df65 100644
--- a/ui/src/widget/resource_tree.rs
+++ b/ui/src/widget/resource_tree.rs
@@ -4,7 +4,7 @@ use anyhow::Error;
use gloo_timers::callback::Timeout;
use serde_json::json;
use web_sys::window;
-use yew::{virtual_dom::Key, Component};
+use yew::{html::IntoEventCallback, virtual_dom::Key, Component};
use pwt::{
css::{FlexFit, FontColor},
@@ -48,6 +48,11 @@ pub struct ResourceTree {
#[builder]
/// If this is true, we wait with the load until we have a search term
pub search_only: bool,
+
+ #[prop_or_default]
+ #[builder_cb(IntoEventCallback, into_event_callback, ())]
+ /// Triggered after the user navigated to an entry by clicking or using the keyboard
+ pub on_navigate: Option<Callback<()>>,
}
impl ResourceTree {
@@ -91,6 +96,7 @@ pub enum Msg {
Load,
LoadResult(Result<Vec<RemoteResources>, Error>),
RemoteListChanged(RemoteList),
+ NavigateToEntry(Key),
}
pub struct PdmResourceTree {
@@ -193,6 +199,32 @@ impl Component for PdmResourceTree {
}
true
}
+ Msg::NavigateToEntry(key) => {
+ let store = self.store.read();
+ let root = store.root().unwrap();
+
+ let mut navigated = false;
+ if let Some(node) = root.find_node_by_key(&key) {
+ match node.record() {
+ PdmTreeEntry::Root => {}
+ PdmTreeEntry::Resource(remote, resource) => {
+ crate::navigate_to(ctx.link(), remote, Some(resource));
+ navigated = true;
+ }
+ PdmTreeEntry::Remote(remote, _) => {
+ crate::navigate_to(ctx.link(), remote, None);
+ navigated = true;
+ }
+ }
+ }
+
+ if navigated {
+ if let Some(cb) = &ctx.props().on_navigate {
+ cb.emit(());
+ }
+ }
+ false
+ }
}
}
@@ -217,30 +249,16 @@ impl Component for PdmResourceTree {
let table = DataTable::new(columns(ctx.link(), self.store.clone()), self.store.clone())
.selection(self.selection.clone())
.on_row_click({
- let store = self.store.clone();
let link = ctx.link().clone();
move |event: &mut DataTableMouseEvent| {
- let store = store.read();
- let root = store.root().unwrap();
-
- if let Some(node) = root.find_node_by_key(&event.record_key) {
- navigate_to_entry(&link, node.record());
- }
+ link.send_message(Msg::NavigateToEntry(event.record_key.clone()));
}
})
.on_row_keydown({
- let store = self.store.clone();
let link = ctx.link().clone();
move |event: &mut DataTableKeyboardEvent| {
- let store = store.read();
- let root = store.root().unwrap();
-
- if event.key().as_str() != "Enter" {
- return;
- }
-
- if let Some(node) = root.find_node_by_key(&event.record_key) {
- navigate_to_entry(&link, node.record());
+ if let "Enter" | " " = event.key().as_str() {
+ link.send_message(Msg::NavigateToEntry(event.record_key.clone()))
}
}
})
@@ -286,18 +304,6 @@ impl Component for PdmResourceTree {
}
}
-fn navigate_to_entry(link: &html::Scope<PdmResourceTree>, record: &PdmTreeEntry) {
- match record {
- PdmTreeEntry::Root => {}
- PdmTreeEntry::Resource(remote, resource) => {
- crate::navigate_to(link, remote, Some(resource));
- }
- PdmTreeEntry::Remote(remote, _) => {
- crate::navigate_to(link, remote, None);
- }
- }
-}
-
fn columns(
link: &html::Scope<PdmResourceTree>,
store: TreeStore<PdmTreeEntry>,
diff --git a/ui/src/widget/search_box.rs b/ui/src/widget/search_box.rs
index 52bb156..3a52411 100644
--- a/ui/src/widget/search_box.rs
+++ b/ui/src/widget/search_box.rs
@@ -40,6 +40,7 @@ pub enum Msg {
ChangeTerm(String, bool), // force value
FocusChange(bool),
ToggleFocus,
+ NavigatedToEntry,
}
pub struct PdmSearchBox {
@@ -105,6 +106,10 @@ impl Component for PdmSearchBox {
self.toggle_focus = true;
true
}
+ Msg::NavigatedToEntry => {
+ self.focus = false;
+ true
+ }
}
}
@@ -126,6 +131,7 @@ impl Component for PdmSearchBox {
.border(true)
.width(CssLength::Fraction(0.5))
.height(400)
+ .on_navigate(ctx.link().callback(|_| Msg::NavigatedToEntry))
.class("pwt-shadow2");
let clear_trigger_icon = if self.search_term.is_empty() {
--
2.47.2
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
next reply other threads:[~2025-09-05 7:30 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-05 7:29 Dominik Csapak [this message]
2025-09-05 12:34 ` [pdm-devel] applied: " Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250905072928.782706-1-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pdm-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.