From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id E16E51FF190 for ; Fri, 10 Jan 2025 11:22:05 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 79A5F2909E; Fri, 10 Jan 2025 11:21:52 +0100 (CET) From: Dominik Csapak To: pdm-devel@lists.proxmox.com Date: Fri, 10 Jan 2025 11:21:41 +0100 Message-Id: <20250110102142.1212874-6-d.csapak@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250110102142.1212874-1-d.csapak@proxmox.com> References: <20250110102142.1212874-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.016 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 datacenter-manager 4/5] ui: generate URLs with the option 'web-url' property 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" This reworks `get_deep_url` so that we use the additional setting for generating the URL. It still falls back to the previous URL generation if either the values are not set, or no valid URL can be constructed. Introduces a helper to extract the node from a resource. Signed-off-by: Dominik Csapak --- ui/src/dashboard/top_entities.rs | 6 ++- ui/src/lib.rs | 75 ++++++++++++++++++++------------ ui/src/pve/mod.rs | 4 +- ui/src/pve/tree.rs | 17 ++++++-- ui/src/widget/resource_tree.rs | 21 +++++---- 5 files changed, 78 insertions(+), 45 deletions(-) diff --git a/ui/src/dashboard/top_entities.rs b/ui/src/dashboard/top_entities.rs index 4bd71b9..af3f853 100644 --- a/ui/src/dashboard/top_entities.rs +++ b/ui/src/dashboard/top_entities.rs @@ -21,7 +21,7 @@ use pwt::{ use pdm_client::types::{Resource, TopEntity}; use crate::{ - get_deep_url, navigate_to, + get_deep_url, get_resource_node, navigate_to, renderer::{render_resource_icon, render_resource_name}, }; @@ -131,6 +131,8 @@ impl Component for TopEntitiesComp { let rrd = &entity.rrd_data; let remote = &entity.remote; + let node = get_resource_node(resource).map(|n| n.to_string()); + let tooltip_anchor = if let Some(info) = self.tooltip_info.as_ref() { if info.id == resource.global_id() { tooltip = Some(create_tooltip(remote, resource, info, &props.metrics_title)); @@ -171,7 +173,7 @@ impl Component for TopEntitiesComp { let remote = remote.clone(); let id = resource.id(); move |_| { - if let Some(url) = get_deep_url(&link, &remote, &id) { + if let Some(url) = get_deep_url(&link, &remote, node.as_deref(), &id) { let _ = web_sys::window().unwrap().open_with_url(&url.href()); } } diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 5a046f6..5c6d076 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,4 +1,5 @@ use pdm_api_types::resource::{PveLxcResource, PveQemuResource}; +use pdm_client::types::Resource; use serde::{Deserialize, Serialize}; mod administration; @@ -78,38 +79,47 @@ pub(crate) fn get_remote( pub(crate) fn get_deep_url( link: &yew::html::Scope, remote: &str, + node: Option<&str>, id: &str, ) -> Option { let remote = get_remote(link, remote)?; - let (default_port, hash) = match remote.ty { - pdm_api_types::remotes::RemoteType::Pve => ( - "8006", - if id.is_empty() { - String::new() - } else { - format!("v1::={id}") - }, - ), - pdm_api_types::remotes::RemoteType::Pbs => ( - "8007", - if id.is_empty() { - String::new() - } else { - format!("DataStore-{id}") - }, - ), + let hash = match (id, remote.ty) { + ("", _) => String::new(), + (id, pdm_api_types::remotes::RemoteType::Pve) => format!("v1::={id}"), + (id, pdm_api_types::remotes::RemoteType::Pbs) => format!("DataStore-{id}"), }; - let node = remote.nodes.first()?; - let url = web_sys::Url::new(&format!("https://{}/", node.hostname)); - if let Ok(url) = url { - if url.port() == "" { - url.set_port(default_port); - } - url.set_hash(&hash); - Some(url) - } else { - None + + let url = match remote.web_url { + Some(web_url) => match (web_url.per_node_template.as_deref(), node) { + (Some(template), Some(node)) => { + web_sys::Url::new(&template.replace("{{nodename}}", node)).ok() + } + _ => web_url + .base_url + .as_ref() + .map(|url| web_sys::Url::new(url).ok()) + .flatten(), + }, + None => None, } + .or_else(|| { + let node = remote.nodes.first()?; + let url = web_sys::Url::new(&format!("https://{}/", node.hostname)); + url.ok().map(|url| { + if url.port() == "" { + let default_port = match remote.ty { + pdm_api_types::remotes::RemoteType::Pve => "8006", + pdm_api_types::remotes::RemoteType::Pbs => "8007", + }; + url.set_port(default_port); + } + url + }) + }); + url.map(|url| { + url.set_hash(&hash); + url + }) } pub(crate) fn navigate_to( @@ -135,3 +145,14 @@ pub(crate) fn navigate_to( nav.push(&yew_router::AnyRoute::new(format!("/remote-{remote}/{id}"))); } } + +pub(crate) fn get_resource_node(resource: &Resource) -> Option<&str> { + match resource { + Resource::PveStorage(storage) => Some(&storage.node), + Resource::PveQemu(qemu) => Some(&qemu.node), + Resource::PveLxc(lxc) => Some(&lxc.node), + Resource::PveNode(node) => Some(&node.node), + Resource::PbsNode(_) => None, + Resource::PbsDatastore(_) => None, + } +} diff --git a/ui/src/pve/mod.rs b/ui/src/pve/mod.rs index 7925bbf..763e91d 100644 --- a/ui/src/pve/mod.rs +++ b/ui/src/pve/mod.rs @@ -181,7 +181,9 @@ impl LoadableComponent for PveRemoteComp { let link = ctx.link().clone(); let remote = ctx.props().remote.clone(); move |_| { - if let Some(url) = get_deep_url(&link.yew_link(), &remote, "") { + if let Some(url) = + get_deep_url(&link.yew_link(), &remote, None, "") + { let _ = window().open_with_url(&url.href()); } } diff --git a/ui/src/pve/tree.rs b/ui/src/pve/tree.rs index 8b1f5ba..50a5ae4 100644 --- a/ui/src/pve/tree.rs +++ b/ui/src/pve/tree.rs @@ -574,7 +574,7 @@ fn columns( DataTableColumn::new(tr!("Actions")) .width("180px") .render(move |entry: &PveTreeNode| { - let (id, local_id, guest_info) = match entry { + let (id, local_id, guest_info, node) = match entry { PveTreeNode::Lxc(r) => { let guest_info = GuestInfo::new(GuestType::Lxc, r.vmid); let local_id = guest_info.local_id(); @@ -582,6 +582,7 @@ fn columns( r.id.as_str(), local_id, Some((guest_info, r.status.as_str())), + Some(r.node.clone()), ) } PveTreeNode::Qemu(r) => { @@ -591,10 +592,16 @@ fn columns( r.id.as_str(), local_id, Some((guest_info, r.status.as_str())), + Some(r.node.clone()), ) } - PveTreeNode::Root => ("root", "root".to_string(), None), - PveTreeNode::Node(r) => (r.id.as_str(), format!("node/{}", r.node), None), + PveTreeNode::Root => ("root", "root".to_string(), None, None), + PveTreeNode::Node(r) => ( + r.id.as_str(), + format!("node/{}", r.node), + None, + Some(r.node.clone()), + ), }; Row::new() @@ -642,7 +649,9 @@ fn columns( let remote = remote.clone(); move |()| { // there must be a remote with a connections config if were already here - if let Some(url) = get_deep_url(link.yew_link(), &remote, &local_id) { + if let Some(url) = + get_deep_url(link.yew_link(), &remote, node.as_deref(), &local_id) + { let _ = window().open_with_url(&url.href()); } } diff --git a/ui/src/widget/resource_tree.rs b/ui/src/widget/resource_tree.rs index 6c4537d..1b764f7 100644 --- a/ui/src/widget/resource_tree.rs +++ b/ui/src/widget/resource_tree.rs @@ -23,7 +23,7 @@ use proxmox_yew_comp::{http_get, Status}; use pdm_api_types::resource::{RemoteResources, Resource}; use crate::{ - get_deep_url, + get_deep_url, get_resource_node, renderer::{render_resource_name, render_status_icon}, RemoteList, }; @@ -321,12 +321,9 @@ fn columns( .render(|item: &PdmTreeEntry| { match item { PdmTreeEntry::Root => "", - PdmTreeEntry::Resource(_, resource) => match resource { - Resource::PveStorage(r) => &r.node, - Resource::PveQemu(r) => &r.node, - Resource::PveLxc(r) => &r.node, - _ => "", - }, + PdmTreeEntry::Resource(_, resource) => { + get_resource_node(&resource).unwrap_or("") + } PdmTreeEntry::Remote(_, _) => "", } .into() @@ -338,13 +335,15 @@ fn columns( .render({ let link = link.clone(); move |item: &PdmTreeEntry| { - let (remote, id) = match item { + let (remote, id, node) = match item { PdmTreeEntry::Root => return html! {}, - PdmTreeEntry::Resource(remote_id, resource) => (remote_id, resource.id()), - PdmTreeEntry::Remote(remote_id, _) => (remote_id, String::new()), + PdmTreeEntry::Resource(remote_id, resource) => { + (remote_id, resource.id(), get_resource_node(resource)) + } + PdmTreeEntry::Remote(remote_id, _) => (remote_id, String::new(), None), }; - match get_deep_url(&link, remote, &id) { + match get_deep_url(&link, remote, node, &id) { Some(url) => ActionIcon::new("fa fa-external-link") .on_activate(move |()| { let _ = window().unwrap().open_with_url(&url.href()); -- 2.39.5 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel