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 53E9F1FF187 for ; Tue, 2 Dec 2025 15:32:37 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id A4DC3148F9; Tue, 2 Dec 2025 15:33:01 +0100 (CET) From: Dominik Csapak To: pdm-devel@lists.proxmox.com Date: Tue, 2 Dec 2025 15:31:07 +0100 Message-ID: <20251202143226.3681712-7-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251202143226.3681712-1-d.csapak@proxmox.com> References: <20251202143226.3681712-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.030 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: show pdm subscription state in top nav bar 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" Just an icon and a very high level (and short) text to not use too much space here. A click on it navigates to the subscription panel (with more details). For this to work, we have to change the subscription laoding in the main entry point a bit, since we now want to always load it, not just when we're freshly logging in. While the icon logic is reused from proxmox-yew-comp, the text is unique here because it has to be short and we don't have that many possible states currently. Signed-off-by: Dominik Csapak --- ui/Cargo.toml | 1 + ui/src/main.rs | 56 +++++++++++++++++++++++++++---------------- ui/src/top_nav_bar.rs | 41 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/ui/Cargo.toml b/ui/Cargo.toml index d58dac37..2d347ad2 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -39,6 +39,7 @@ proxmox-client = "1" proxmox-human-byte = "1" proxmox-login = "1" proxmox-schema = "5" +proxmox-subscription = { version = "1.0.1", features = ["api-types"], default-features = false } proxmox-rrd-api-types = "1" proxmox-node-status = "1" pbs-api-types = { version = "1.0.3", features = [ "enum-fallback" ] } diff --git a/ui/src/main.rs b/ui/src/main.rs index 63ac1431..bc8143a6 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -1,6 +1,6 @@ use anyhow::Error; use gloo_timers::callback::Timeout; -use serde_json::json; +use serde_json::{json, Value}; use wasm_bindgen::JsCast; use web_sys::HtmlElement; @@ -16,15 +16,16 @@ use pbs_api_types::TaskListItem; use proxmox_login::Authentication; use proxmox_yew_comp::utils::init_task_descr_table_base; use proxmox_yew_comp::{ - authentication_from_cookie, http_get, register_auth_observer, AclContextProvider, AuthObserver, - LoginPanel, SubscriptionAlert, + authentication_from_cookie, http_get, register_auth_observer, subscription_is_active, + AclContextProvider, AuthObserver, LoginPanel, SubscriptionAlert, }; //use pbs::MainMenu; +use pdm_api_types::subscription::PdmSubscriptionInfo; use pdm_api_types::views::ViewConfig; use pdm_ui::{ - check_subscription, register_pve_tasks, MainMenu, RemoteList, RemoteListCacheEntry, - SearchProvider, TopNavBar, ViewListContext, + register_pve_tasks, MainMenu, RemoteList, RemoteListCacheEntry, SearchProvider, TopNavBar, + ViewListContext, }; type MsgRemoteList = Result; @@ -40,12 +41,14 @@ enum Msg { RemoteList(MsgRemoteList), ViewList(MsgViewList), UpdateViewList, + UpdateSubscriptionInfo(Result, bool), // fresh login } struct DatacenterManagerApp { _auth_observer: AuthObserver, login_info: Option, subscription_confirmed: bool, + subscription: Option, show_subscription_alert: Option, running_tasks: Loader>, running_tasks_timeout: Option, @@ -74,21 +77,12 @@ impl DatacenterManagerApp { fn on_login(&mut self, ctx: &Context, fresh_login: bool) { if let Some(info) = &self.login_info { self.running_tasks.load(); - if fresh_login { - if self.subscription_confirmed { - ctx.link().send_message(Msg::ConfirmSubscription); - } else { - self.async_pool.send_future(ctx.link().clone(), async move { - let is_active = check_subscription().await; - - if !is_active { - Msg::ShowSubscriptionAlert - } else { - Msg::ConfirmSubscription - } - }); - } - } else { + let link = ctx.link().clone(); + self.async_pool.spawn(async move { + let data = http_get("/nodes/localhost/subscription", None).await; + link.send_message(Msg::UpdateSubscriptionInfo(data, fresh_login)); + }); + if !fresh_login { ctx.link().send_message(Msg::ConfirmSubscription); proxmox_yew_comp::http_set_auth(info.clone()); } @@ -209,6 +203,7 @@ impl Component for DatacenterManagerApp { _auth_observer, login_info, subscription_confirmed: false, + subscription: None, show_subscription_alert: None, running_tasks, running_tasks_timeout: None, @@ -229,6 +224,27 @@ impl Component for DatacenterManagerApp { fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { + Msg::UpdateSubscriptionInfo(data, fresh_login) => { + if fresh_login { + let message = if self.subscription_confirmed { + Msg::ConfirmSubscription + } else { + let is_active = subscription_is_active(Some(&data)); + + if !is_active { + Msg::ShowSubscriptionAlert + } else { + Msg::ConfirmSubscription + } + }; + ctx.link().send_message(message); + } + self.subscription = data + .map(|value| serde_json::from_value::(value).ok()) + .ok() + .flatten(); + true + } Msg::ConfirmSubscription => { self.subscription_confirmed = true; self.show_subscription_alert = Some(false); diff --git a/ui/src/top_nav_bar.rs b/ui/src/top_nav_bar.rs index 4c63e013..a99dc7ff 100644 --- a/ui/src/top_nav_bar.rs +++ b/ui/src/top_nav_bar.rs @@ -10,10 +10,13 @@ use pwt::widget::menu::{Menu, MenuButton, MenuEntry, MenuEvent, MenuItem}; use pwt::AsyncAbortGuard; use yew::html::{IntoEventCallback, IntoPropValue}; use yew::virtual_dom::{VComp, VNode}; +use yew_router::prelude::RouterScopeExt; +use yew_router::AnyRoute; use pwt::state::{Loader, Theme, ThemeObserver}; use pwt::widget::{Button, Container, Row, ThemeModeSelector, Tooltip}; +use proxmox_subscription::SubscriptionStatus; use proxmox_yew_comp::utils::set_location_href; use proxmox_yew_comp::RunningTasksButton; use proxmox_yew_comp::{http_get, LanguageDialog, TaskViewer, ThemeDialog}; @@ -21,6 +24,7 @@ use proxmox_yew_comp::{http_get, LanguageDialog, TaskViewer, ThemeDialog}; use pwt_macros::builder; use pbs_api_types::TaskListItem; +use pdm_api_types::subscription::PdmSubscriptionInfo; use pdm_api_types::RemoteUpid; use crate::tasks::format_optional_remote_upid; @@ -42,6 +46,11 @@ async fn load_version() -> Result { pub struct TopNavBar { running_tasks: Loader>, + #[builder(IntoPropValue, into_prop_value)] + #[prop_or_default] + /// Used to show the subscription validity + subscription_info: Option, + #[builder_cb(IntoEventCallback, into_event_callback, ())] #[prop_or_default] pub on_logout: Option>, @@ -284,6 +293,18 @@ impl Component for PdmTopNavBar { {"BETA"} }) + .with_child( + show_subscription_notice(props.subscription_info.clone()) + .class("pwt-pointer") + .onclick({ + let link = ctx.link().clone(); + move |_| { + if let Some(nav) = link.navigator() { + nav.push(&AnyRoute::new("/subscription")); + } + } + }), + ) .with_flex_spacer() .with_child(SearchBox::new()) .with_flex_spacer() @@ -299,3 +320,23 @@ impl From for VNode { VNode::from(comp) } } + +fn show_subscription_notice(subscriptions: Option) -> Row { + let subscription = subscriptions.unwrap_or_default(); + let icon = proxmox_yew_comp::subscription_icon(&subscription.info.status.to_string()); + + // not the same as in proxmox-yew-comp, because + // 1. pdm does not have its own subscription + // 2. the text must be short for the top nav bar + let text = match subscription.info.status { + SubscriptionStatus::Active => tr!("Valid subscription"), + SubscriptionStatus::NotFound => tr!("No valid subscription"), + _ => tr!("Invalid subscription state"), + }; + + Row::new() + .padding_x(2) + .gap(2) + .with_child(Container::new().with_child(icon.large())) + .with_child(Container::new().with_child(text)) +} -- 2.47.3 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel