From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id A6D921FF178 for ; Mon, 1 Dec 2025 16:31:23 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6DBE420FD7; Mon, 1 Dec 2025 16:31:47 +0100 (CET) From: Hannes Laimer To: pdm-devel@lists.proxmox.com Date: Mon, 1 Dec 2025 16:31:09 +0100 Message-ID: <20251201153109.274759-3-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251201153109.274759-1-h.laimer@proxmox.com> References: <20251201153109.274759-1-h.laimer@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1764603031725 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.051 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH proxmox-datacenter-manager 2/2] ui: firewall: add link to pve to rules/options panel X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Datacenter Manager development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" Signed-off-by: Hannes Laimer --- ui/src/remotes/firewall/tree.rs | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/ui/src/remotes/firewall/tree.rs b/ui/src/remotes/firewall/tree.rs index 18510b5..ad538e0 100644 --- a/ui/src/remotes/firewall/tree.rs +++ b/ui/src/remotes/firewall/tree.rs @@ -1,4 +1,5 @@ use futures::Future; +use gloo_utils::window; use std::pin::Pin; use std::rc::Rc; use yew::{ContextHandle, Html}; @@ -139,6 +140,7 @@ pub enum Msg { nodes: Vec, }, SelectionChanged, + TabChanged, ToggleTreePanel, Error(FirewallError), NoOp, @@ -147,6 +149,7 @@ pub enum Msg { pub struct FirewallTreeComponent { store: TreeStore, selection: Selection, + tab_selection: Selection, _context_listener: ContextHandle, filter_text: String, scope: Scope, @@ -169,6 +172,46 @@ impl FirewallTreeComponent { self.selected_entry = None; } + fn get_pve_url(&self, ctx: &LoadableComponentContext, tab: &str) -> Option { + let entry = self.selected_entry.as_ref()?; + let (remote, node, vmid, kind) = match entry { + TreeEntry::Remote(r) => (r.name.as_str(), None, None, None), + TreeEntry::Node(n) => (n.remote.as_str(), Some(n.name.as_str()), None, None), + TreeEntry::Guest(g, kind) => ( + g.remote.as_str(), + Some(g.node.as_str()), + Some(g.guest.vmid), + Some(kind), + ), + _ => return None, + }; + + let is_options = tab == "options"; + let index = if is_options { 36 } else { 32 }; + + match (node, vmid, kind) { + (None, None, _) => { + let id = format!("v1:0:18:4:::::::{index}"); + let url = crate::get_deep_url_low_level(ctx.link().yew_link(), remote, None, &id)?; + Some(url.href()) + } + (Some(node), None, _) => { + let id = format!("node/{node}:4:{index}"); + let url = crate::get_deep_url(ctx.link().yew_link(), remote, Some(node), &id)?; + Some(url.href()) + } + (Some(node), Some(vmid), Some(kind)) => { + let id = match kind { + GuestKind::Lxc => format!("lxc/{vmid}:4::::::{index}"), + GuestKind::Qemu => format!("qemu/{vmid}:4:::::{index}"), + }; + let url = crate::get_deep_url(ctx.link().yew_link(), remote, Some(node), &id)?; + Some(url.href()) + } + _ => None, + } + } + fn handle_scope_change(&mut self, ctx: &LoadableComponentContext, new_scope: Scope) { let remote_changed = self.scope.remote_name() != new_scope.remote_name(); @@ -301,10 +344,28 @@ impl FirewallTreeComponent { config.title }; + let current_tab = self + .tab_selection + .selected_key() + .map(|k| k.to_string()) + .unwrap_or_else(|| "rules".to_string()); + + let pve_url = self.get_pve_url(ctx, ¤t_tab); + let mut tab_panel = TabPanel::new() + .selection(self.tab_selection.clone()) .class(css::FlexFit) .class(css::ColorScheme::Neutral) .title(title) + .tool( + Button::new(tr!("Open Web UI")) + .icon_class("fa fa-external-link") + .on_activate(move |_| { + if let Some(url) = &pve_url { + let _ = window().open_with_url(url); + } + }), + ) .with_item_builder( TabBarItem::new() .key("rules") @@ -403,6 +464,8 @@ impl LoadableComponent for FirewallTreeComponent { let selection = Selection::new() .on_select(link.callback(|_selection: Selection| Msg::SelectionChanged)); + let tab_selection = Selection::new().on_select(link.callback(|_| Msg::TabChanged)); + let (_, context_listener) = ctx .link() .yew_link() @@ -413,6 +476,7 @@ impl LoadableComponent for FirewallTreeComponent { Self { store, selection, + tab_selection, _context_listener: context_listener, filter_text: String::new(), scope: Scope::default(), @@ -533,6 +597,7 @@ impl LoadableComponent for FirewallTreeComponent { } true } + Msg::TabChanged => true, Msg::ToggleTreePanel => { self.tree_collapsed = !self.tree_collapsed; true -- 2.47.3 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel