* [pdm-devel] [PATCH datacenter-manager 2/3] ui: dashboard/views: add subscription notice in status row
2025-12-03 9:59 [pdm-devel] [PATCH datacenter-manager 1/3] ui: mark subscription check as active if no remotes are configured Dominik Csapak
@ 2025-12-03 9:59 ` Dominik Csapak
2025-12-03 9:59 ` [pdm-devel] [PATCH datacenter-manager 3/3] ui: views: make Subscription panel not required anymore Dominik Csapak
2025-12-03 12:08 ` [pdm-devel] [PATCH datacenter-manager 1/3] ui: mark subscription check as active if no remotes are configured Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Dominik Csapak @ 2025-12-03 9:59 UTC (permalink / raw)
To: pdm-devel
This adds a short subscription notice to the status row.
It will be loaded together with the normal refresh.
It currently only shows the following states:
* No remotes configured (warning)
* No valid subscriptions (error)
* Valid subscriptions (good)
It reuses the pdm backend subscription check for this.
If there is a message or an error from the api call, show that as
tooltip.
A click on the notice routes to the subscriptions panel of PDM, where
more info about the statistics is outlined.
Downside of this approach is that we might load the subscription info
twice on a fresh login, once for the login popup check, and once for the
dashboard/view if one is open after login.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/Cargo.toml | 1 +
ui/src/dashboard/status_row.rs | 86 ++++++++++++++++++++++++++++++++--
2 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/ui/Cargo.toml b/ui/Cargo.toml
index 12c1ff45..d5124340 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/dashboard/status_row.rs b/ui/src/dashboard/status_row.rs
index e1af6697..582a9b87 100644
--- a/ui/src/dashboard/status_row.rs
+++ b/ui/src/dashboard/status_row.rs
@@ -1,19 +1,27 @@
+use anyhow::Error;
use gloo_timers::callback::Interval;
use yew::html::IntoPropValue;
use yew::{Component, Properties};
+use yew_router::prelude::RouterScopeExt;
+use yew_router::AnyRoute;
-use pwt::css;
use pwt::prelude::*;
use pwt::state::SharedState;
+use pwt::{css, AsyncPool};
use pwt::{
css::AlignItems,
widget::{ActionIcon, Container, Row, Tooltip},
};
use pwt_macros::{builder, widget};
+use proxmox_subscription::SubscriptionStatus;
+use proxmox_yew_comp::subscription_icon;
use proxmox_yew_comp::utils::render_epoch;
+use pdm_api_types::subscription::PdmSubscriptionInfo;
+
use crate::dashboard::view::EditingMessage;
+use crate::LoadResult;
#[widget(comp=PdmDashboardStatusRow)]
#[derive(Properties, PartialEq, Clone)]
@@ -51,6 +59,7 @@ impl DashboardStatusRow {
pub enum Msg {
/// The bool denotes if the reload comes from the click or the timer.
Reload(bool),
+ SubscriptionInfoLoaded(Result<PdmSubscriptionInfo, Error>),
Edit(EditingMessage),
}
@@ -59,6 +68,9 @@ pub struct PdmDashboardStatusRow {
_interval: Interval,
loading: bool,
edit: bool,
+
+ async_pool: AsyncPool,
+ subscription_info: LoadResult<PdmSubscriptionInfo, Error>,
}
impl PdmDashboardStatusRow {
@@ -73,6 +85,13 @@ impl PdmDashboardStatusRow {
_interval
}
+
+ fn load_subscription(&self, ctx: &yew::Context<Self>) {
+ self.async_pool.send_future(ctx.link().clone(), async move {
+ let res = proxmox_yew_comp::http_get("/nodes/localhost/subscription", None).await;
+ Msg::SubscriptionInfoLoaded(res)
+ });
+ }
}
impl Component for PdmDashboardStatusRow {
@@ -80,11 +99,15 @@ impl Component for PdmDashboardStatusRow {
type Properties = DashboardStatusRow;
fn create(ctx: &yew::Context<Self>) -> Self {
- Self {
+ let this = Self {
_interval: Self::create_interval(ctx),
loading: false,
edit: false,
- }
+ async_pool: AsyncPool::new(),
+ subscription_info: LoadResult::new(),
+ };
+ this.load_subscription(ctx);
+ this
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
@@ -92,6 +115,7 @@ impl Component for PdmDashboardStatusRow {
match msg {
Msg::Reload(clicked) => {
props.on_reload.emit(clicked);
+ self.load_subscription(ctx);
self.loading = true;
true
}
@@ -102,6 +126,10 @@ impl Component for PdmDashboardStatusRow {
}
true
}
+ Msg::SubscriptionInfoLoaded(res) => {
+ self.subscription_info.update(res);
+ true
+ }
}
}
@@ -116,7 +144,8 @@ impl Component for PdmDashboardStatusRow {
fn view(&self, ctx: &yew::Context<Self>) -> yew::Html {
let props = ctx.props();
- let is_loading = props.last_refresh.is_none() || self.loading;
+ let is_loading =
+ props.last_refresh.is_none() || self.loading || !self.subscription_info.has_data();
let on_settings_click = props.on_settings_click.clone();
Row::new()
.gap(1)
@@ -141,6 +170,18 @@ impl Component for PdmDashboardStatusRow {
}
None => tr!("Now refreshing"),
}))
+ .with_optional_child(create_subscription_notice(&self.subscription_info).map(
+ |element| {
+ element.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_optional_child(props.editing_state.clone().and_then(|_| {
(!self.edit).then_some({
@@ -190,3 +231,40 @@ impl Component for PdmDashboardStatusRow {
.into()
}
}
+
+fn create_subscription_notice(
+ subscriptions: &LoadResult<PdmSubscriptionInfo, Error>,
+) -> Option<Tooltip> {
+ if !subscriptions.has_data() {
+ return None;
+ }
+ let mut text = tr!("No valid subscriptions");
+ let mut icon = subscription_icon(&SubscriptionStatus::NotFound.to_string());
+ let mut tooltip = None;
+
+ if let Some(subscriptions) = &subscriptions.data {
+ if subscriptions.statistics.total_nodes == 0 {
+ text = tr!("No remotes configured");
+ icon = subscription_icon("unknown");
+ } else if let SubscriptionStatus::Active = subscriptions.info.status {
+ text = tr!("Valid subscriptions");
+ icon = subscription_icon(&subscriptions.info.status.to_string());
+ } else if let Some(msg) = &subscriptions.info.message {
+ tooltip = Some(msg.clone());
+ }
+ } else if let Some(err) = &subscriptions.error {
+ tooltip = Some(err.to_string())
+ }
+
+ Some(
+ Tooltip::new(
+ Row::new()
+ .padding_x(2)
+ .gap(2)
+ .class(css::AlignItems::Center)
+ .with_child(icon.large())
+ .with_child(Container::new().with_child(text)),
+ )
+ .tip(tooltip),
+ )
+}
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 4+ messages in thread* [pdm-devel] [PATCH datacenter-manager 3/3] ui: views: make Subscription panel not required anymore
2025-12-03 9:59 [pdm-devel] [PATCH datacenter-manager 1/3] ui: mark subscription check as active if no remotes are configured Dominik Csapak
2025-12-03 9:59 ` [pdm-devel] [PATCH datacenter-manager 2/3] ui: dashboard/views: add subscription notice in status row Dominik Csapak
@ 2025-12-03 9:59 ` Dominik Csapak
2025-12-03 12:08 ` [pdm-devel] [PATCH datacenter-manager 1/3] ui: mark subscription check as active if no remotes are configured Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Dominik Csapak @ 2025-12-03 9:59 UTC (permalink / raw)
To: pdm-devel
Since we now show the subscription state of pdm always in the status row,
the subscription panel in views are useful, but not required anymore.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
ui/src/dashboard/view.rs | 38 +-------------------------------------
1 file changed, 1 insertion(+), 37 deletions(-)
diff --git a/ui/src/dashboard/view.rs b/ui/src/dashboard/view.rs
index 0606f1a9..f45f4622 100644
--- a/ui/src/dashboard/view.rs
+++ b/ui/src/dashboard/view.rs
@@ -12,7 +12,7 @@ use pwt::css;
use pwt::prelude::*;
use pwt::props::StorageLocation;
use pwt::state::{PersistentState, SharedState};
-use pwt::widget::{error_message, form::FormContext, Column, Container, Progress, Row};
+use pwt::widget::{error_message, form::FormContext, Column, Container, Progress};
use pwt::AsyncPool;
use crate::dashboard::refresh_config_edit::{
@@ -288,23 +288,6 @@ fn required_api_calls(layout: &ViewLayout) -> (bool, bool, bool) {
(status, top_entities, task_statistics)
}
-fn has_sub_panel(layout: Option<&ViewTemplate>) -> bool {
- match layout.map(|template| &template.layout) {
- Some(ViewLayout::Rows { rows }) => {
- for row in rows {
- for item in row {
- if item.r#type == WidgetType::Subscription {
- return true;
- }
- }
- }
- }
- None => {}
- }
-
- false
-}
-
impl Component for ViewComp {
type Message = Msg;
type Properties = View;
@@ -479,25 +462,6 @@ impl Component for ViewComp {
),
);
- if !has_sub_panel(self.template.data.as_ref()) {
- let subs = self.render_args.subscriptions.clone();
- let link = ctx.link().clone();
- view.add_child(
- Row::new()
- .padding_x(4)
- .padding_bottom(4)
- .padding_top(0)
- .class("pwt-content-spacer-colors")
- .with_child(
- create_subscription_panel(
- subs.clone(),
- link.clone()
- .callback(move |_| Msg::ShowSubscriptionsDialog(true)),
- )
- .flex(1.0),
- ),
- );
- }
match self.template.data.as_ref().map(|template| &template.layout) {
Some(ViewLayout::Rows { rows }) => {
view.add_child(
--
2.47.3
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 4+ messages in thread