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 A12321FF179 for ; Wed, 10 Dec 2025 15:00:01 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id BCFE31D403; Wed, 10 Dec 2025 15:00:41 +0100 (CET) From: Dominik Csapak To: pdm-devel@lists.proxmox.com Date: Wed, 10 Dec 2025 14:59:59 +0100 Message-ID: <20251210140008.3046928-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.021 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 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [lib.rs] URIBL_SBL_A 0.1 Contains URL's A record listed in the Spamhaus SBL blocklist [188.114.96.3] Subject: [pdm-devel] [PATCH datacenter-manager] ui: add download button for system report 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" by simply setting the 'href' of an 'a' tag to be the report as inline data, like we do on PVE/PBS with a slight difference: in PVE/PBS we create an 'a' tag dynamically on button click, but here we create the a tag when we have the data and wrap a button without click handler, so the click on the button triggers the download of the 'a' tag. Refactor the `get_nodename` function to another place where we can access it from here. Signed-off-by: Dominik Csapak --- ui/Cargo.toml | 1 + ui/src/administration/node_status.rs | 45 +++++++++++++++++++++++----- ui/src/lib.rs | 16 ++++++++++ ui/src/remotes/wizard_page_info.rs | 16 +--------- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 1b4f0a23..9bbde7d1 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -41,6 +41,7 @@ proxmox-login = "1" proxmox-schema = "5" proxmox-subscription = { version = "1.0.1", features = ["api-types"], default-features = false } proxmox-rrd-api-types = "1" +proxmox-time = "2" proxmox-node-status = "1" pbs-api-types = { version = "1.0.3", features = [ "enum-fallback" ] } diff --git a/ui/src/administration/node_status.rs b/ui/src/administration/node_status.rs index 26b6c958..a61f25a2 100644 --- a/ui/src/administration/node_status.rs +++ b/ui/src/administration/node_status.rs @@ -4,12 +4,16 @@ use anyhow::Error; use yew::virtual_dom::{VComp, VNode}; use proxmox_node_status::NodePowerCommand; -use proxmox_yew_comp::utils::copy_text_to_clipboard; +use proxmox_time::epoch_i64; +use proxmox_yew_comp::percent_encoding::percent_encode_component; +use proxmox_yew_comp::utils::{copy_text_to_clipboard, render_epoch}; use proxmox_yew_comp::{http_post, ConfirmButton, NodeStatusPanel}; use pwt::prelude::*; use pwt::widget::{Button, Column, Container, Row}; use pwt::AsyncAbortGuard; +use crate::get_nodename; + #[derive(Properties, Clone, PartialEq)] pub(crate) struct NodeStatus {} @@ -74,12 +78,39 @@ impl PdmNodeStatus { .with_child(&report), ) .with_child( - Row::new().padding(2).with_flex_spacer().with_child( - Button::new(tr!("Copy to clipboard")) - .icon_class("fa fa-clipboard") - .class(pwt::css::ColorScheme::Primary) - .on_activate(move |_| copy_text_to_clipboard(&report)), - ), + Row::new() + .padding(2) + .gap(1) + .with_flex_spacer() + .with_child( + Button::new(tr!("Copy to clipboard")) + .icon_class("fa fa-clipboard") + .class(pwt::css::ColorScheme::Primary) + .on_activate({ + let report = report.clone(); + move |_| copy_text_to_clipboard(&report) + }), + ) + .with_child({ + let button = Button::new(tr!("Download")) + .icon_class("fa fa-download") + .class(pwt::css::ColorScheme::Primary); + + let data = format!( + "data:text/plain;charset=utf-8,{}", + percent_encode_component(&report) + ); + let timestamp = render_epoch(epoch_i64()); + + let filename = match get_nodename() { + Some(nodename) => { + format!("{nodename}-pdm-report-{timestamp}.txt") + } + None => format!("pdm-report-{timestamp}.txt"), + }; + + html! { {button} } + }), ) .into() }) diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 1aac7571..e693ee76 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,3 +1,5 @@ +use gloo_utils::format::JsValueSerdeExt; +use gloo_utils::window; use js_sys::{Array, JsString, Object}; use pdm_api_types::remote_updates::RemoteUpdateSummary; use pdm_api_types::remotes::RemoteType; @@ -37,6 +39,7 @@ pub use search_provider::SearchProvider; mod dashboard; +use wasm_bindgen::JsValue; use yew::html::IntoEventCallback; use yew::Html; use yew_router::prelude::RouterScopeExt; @@ -303,3 +306,16 @@ pub fn extract_package_version( version.parse().ok() } + +#[derive(Deserialize)] +struct ProxmoxServerConfig { + #[serde(alias = "NodeName")] + pub node_name: String, +} + +/// Returns the nodename from the index if set +pub fn get_nodename() -> Option { + let value = js_sys::Reflect::get(&window(), &JsValue::from_str("Proxmox")).ok()?; + let config: ProxmoxServerConfig = JsValueSerdeExt::into_serde(&value).ok()?; + Some(config.node_name) +} diff --git a/ui/src/remotes/wizard_page_info.rs b/ui/src/remotes/wizard_page_info.rs index fbe57d63..4551212e 100644 --- a/ui/src/remotes/wizard_page_info.rs +++ b/ui/src/remotes/wizard_page_info.rs @@ -1,10 +1,8 @@ use std::rc::Rc; use anyhow::Error; -use gloo_utils::{format::JsValueSerdeExt, window}; use html::IntoEventCallback; use serde::{Deserialize, Serialize}; -use wasm_bindgen::JsValue; use yew::virtual_dom::{Key, VComp, VNode}; use proxmox_schema::property_string::PropertyString; @@ -25,7 +23,7 @@ use pdm_api_types::remotes::{NodeUrl, Remote, RemoteType, REMOTE_ID_SCHEMA}; use pwt_macros::builder; use super::wizard_page_connect::ConnectParams; -use crate::widget::PveRealmSelector; +use crate::{get_nodename, widget::PveRealmSelector}; #[derive(Clone, PartialEq, Properties)] #[builder] @@ -414,15 +412,3 @@ impl From for VNode { VNode::from(comp) } } - -#[derive(Deserialize)] -struct ProxmoxServerConfig { - #[serde(alias = "NodeName")] - pub node_name: String, -} - -fn get_nodename() -> Option { - let value = js_sys::Reflect::get(&window(), &JsValue::from_str("Proxmox")).ok()?; - let config: ProxmoxServerConfig = JsValueSerdeExt::into_serde(&value).ok()?; - Some(config.node_name) -} -- 2.47.3 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel