[pdm-devel] [PATCH datacenter-manager v5 24/26] api-types/ui: add ResourceTree variant for WidgetType

Dominik Csapak d.csapak at proxmox.com
Wed Nov 26 16:18:17 CET 2025


this is the resource tree from the search, but contained within a panel
and with search field in a toolbar, for use in the custom views.

This can come in handy, since it gives an overview of the filtered
resources.

It does not refresh together with the other panels in the view
currently, only once at the beginning and when the search term changes.

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
 lib/pdm-api-types/src/views.rs    |  1 +
 ui/src/dashboard/mod.rs           |  3 ++
 ui/src/dashboard/resource_tree.rs | 46 +++++++++++++++++++++++++++++++
 ui/src/dashboard/view.rs          |  6 +++-
 ui/src/dashboard/view/row_view.rs |  4 +++
 5 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 ui/src/dashboard/resource_tree.rs

diff --git a/lib/pdm-api-types/src/views.rs b/lib/pdm-api-types/src/views.rs
index c9864718..1bcde477 100644
--- a/lib/pdm-api-types/src/views.rs
+++ b/lib/pdm-api-types/src/views.rs
@@ -291,6 +291,7 @@ pub enum WidgetType {
     TaskSummary {
         grouping: TaskSummaryGrouping,
     },
+    ResourceTree,
 }
 
 #[derive(Serialize, Deserialize, PartialEq, Clone, Copy)]
diff --git a/ui/src/dashboard/mod.rs b/ui/src/dashboard/mod.rs
index 8800102f..17e5ccd3 100644
--- a/ui/src/dashboard/mod.rs
+++ b/ui/src/dashboard/mod.rs
@@ -39,6 +39,9 @@ pub mod view;
 mod refresh_config_edit;
 pub use refresh_config_edit::create_refresh_config_edit_window;
 
+mod resource_tree;
+pub use resource_tree::create_resource_tree;
+
 fn loading_column() -> Column {
     Column::new()
         .padding(4)
diff --git a/ui/src/dashboard/resource_tree.rs b/ui/src/dashboard/resource_tree.rs
new file mode 100644
index 00000000..cd7a1702
--- /dev/null
+++ b/ui/src/dashboard/resource_tree.rs
@@ -0,0 +1,46 @@
+use pwt::css;
+use pwt::prelude::*;
+use pwt::props::{ContainerBuilder, WidgetBuilder, WidgetStyleBuilder};
+use pwt::widget::form::Field;
+use pwt::widget::Column;
+use pwt::widget::Panel;
+use pwt::widget::Row;
+use pwt::widget::Toolbar;
+
+use crate::widget::ResourceTree;
+
+#[function_component]
+fn ResourceTreeWithSearch() -> Html {
+    let search = use_state(String::new);
+
+    Column::new()
+        .class(css::FlexFit)
+        .with_child(
+            Toolbar::new()
+                .with_child(tr!("Search"))
+                .with_child(Field::new().on_change({
+                    let search = search.clone();
+                    move |value| search.set(value)
+                })),
+        )
+        .with_child(
+            // use another flex layout with base width to work around the data tables dynamic
+            // column size that does not decrease
+            Row::new().class(css::FlexFit).with_child(
+                ResourceTree::new()
+                    .search_term(search.to_string())
+                    .flex(1.0)
+                    .width(250)
+                    .height(500)
+                    .class(css::FlexFit),
+            ),
+        )
+        .into()
+}
+
+pub fn create_resource_tree() -> Panel {
+    Panel::new()
+        .class(css::FlexFit)
+        .title(tr!("Resources"))
+        .with_child(html! {<ResourceTreeWithSearch />})
+}
diff --git a/ui/src/dashboard/view.rs b/ui/src/dashboard/view.rs
index ff287db8..e6a86bc9 100644
--- a/ui/src/dashboard/view.rs
+++ b/ui/src/dashboard/view.rs
@@ -24,7 +24,7 @@ use crate::dashboard::subscription_info::create_subscriptions_dialog;
 use crate::dashboard::tasks::get_task_options;
 use crate::dashboard::{
     create_guest_panel, create_node_panel, create_pbs_datastores_panel,
-    create_refresh_config_edit_window, create_remote_panel, create_sdn_panel,
+    create_refresh_config_edit_window, create_remote_panel, create_resource_tree, create_sdn_panel,
     create_subscription_panel, create_task_summary_panel, create_top_entities_panel,
     DashboardStatusRow,
 };
@@ -161,6 +161,7 @@ fn render_widget(
             let (hours, since) = get_task_options(refresh_config.task_last_hours);
             create_task_summary_panel(statistics, remotes, hours, since)
         }
+        WidgetType::ResourceTree => create_resource_tree(),
     };
 
     if let Some(title) = &item.title {
@@ -269,6 +270,9 @@ fn required_api_calls(layout: &ViewLayout) -> (bool, bool, bool) {
                         }
                         WidgetType::Leaderboard { .. } => top_entities = true,
                         WidgetType::TaskSummary { .. } => task_statistics = true,
+                        WidgetType::ResourceTree => {
+                            // each list must do it itself
+                        }
                     }
                 }
             }
diff --git a/ui/src/dashboard/view/row_view.rs b/ui/src/dashboard/view/row_view.rs
index 7ecac200..df5552c3 100644
--- a/ui/src/dashboard/view/row_view.rs
+++ b/ui/src/dashboard/view/row_view.rs
@@ -625,4 +625,8 @@ fn create_menu(ctx: &yew::Context<RowViewComp>, new_coords: Position) -> Menu {
             ),
         )
         .with_item(MenuItem::new(tr!("SDN Panel")).on_select(create_callback(WidgetType::Sdn)))
+        .with_item(
+            MenuItem::new(tr!("Resource Tree"))
+                .on_select(create_callback(WidgetType::ResourceTree)),
+        )
 }
-- 
2.47.3





More information about the pdm-devel mailing list