public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel
@ 2025-12-02 14:31 Dominik Csapak
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature Dominik Csapak
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

This adds a dedicated subscription panel for pdm, and adds the overall subscription
state to the top nav bar.

This means we can drop the required subscription panel for the views.

I opted for not removing the subscription panel from the default dashboard,
but if that's wanted it is not a big change.

Note that the first proxmox-yew-comp patch breaks current pdm, since a
public function signature changes.

proxmox-yew-comp:

Dominik Csapak (2):
  subscription check: use more useful function signature
  subscriptions: expose subscription_icon

 src/apt_package_manager.rs | 2 +-
 src/apt_repositories.rs    | 2 +-
 src/lib.rs                 | 4 +++-
 src/subscription_alert.rs  | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)


proxmox-datacenter-manager:

Dominik Csapak (5):
  ui: adapt to signature change of subscription_is_active
  lib/server: include subscription statistics in subscription
    information
  ui: configuration: add subscription panel
  ui: show pdm subscription state in top nav bar
  ui: views: make Subscription panel not required anymore

 lib/pdm-api-types/src/subscription.rs      |  20 ++-
 server/src/api/nodes/subscription.rs       |  24 +--
 ui/Cargo.toml                              |   1 +
 ui/src/configuration/mod.rs                |   2 +
 ui/src/configuration/subscription_panel.rs | 187 +++++++++++++++++++++
 ui/src/dashboard/view.rs                   |  38 +----
 ui/src/lib.rs                              |   2 +-
 ui/src/main.rs                             |  56 +++---
 ui/src/main_menu.rs                        |  18 +-
 ui/src/top_nav_bar.rs                      |  41 +++++
 10 files changed, 318 insertions(+), 71 deletions(-)
 create mode 100644 ui/src/configuration/subscription_panel.rs


Summary over all repositories:
  14 files changed, 324 insertions(+), 75 deletions(-)

-- 
Generated by git-murpp 0.8.1


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 15:23   ` [pdm-devel] applied: " Thomas Lamprecht
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 2/2] subscriptions: expose subscription_icon Dominik Csapak
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

having a reference of an option is very unweildly at times, e.g. when
having the inner type, it's necessary to move it into an option, even if
`subscription_is_active` does not need to own the data.

using an option of a reference makes usage much more ergonomic at times.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
NOTE: this breaks current pdm, as it changes a public function
signature. Fix for pdm is the first datacenter manger patch.

 src/apt_package_manager.rs | 2 +-
 src/apt_repositories.rs    | 2 +-
 src/subscription_alert.rs  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/apt_package_manager.rs b/src/apt_package_manager.rs
index 0b4ae2e..b419957 100644
--- a/src/apt_package_manager.rs
+++ b/src/apt_package_manager.rs
@@ -198,7 +198,7 @@ impl LoadableComponent for ProxmoxAptPackageManager {
                 let command = format!("{}/update", props.base_url);
                 self.async_pool.spawn(async move {
                     let data = crate::http_get::<Value>(url.as_str(), None).await;
-                    let is_active = subscription_is_active(&Some(data));
+                    let is_active = subscription_is_active(Some(&data));
 
                     if is_active {
                         link.task_base_url(task_base_url);
diff --git a/src/apt_repositories.rs b/src/apt_repositories.rs
index 9ab8258..7157c0c 100644
--- a/src/apt_repositories.rs
+++ b/src/apt_repositories.rs
@@ -705,7 +705,7 @@ fn standard_repo_info(
 
 impl ProxmoxAptRepositories {
     fn active_subscription(&self) -> bool {
-        subscription_is_active(&self.subscription_status)
+        subscription_is_active(self.subscription_status.as_ref())
     }
 
     fn create_show_subscription_dialog(
diff --git a/src/subscription_alert.rs b/src/subscription_alert.rs
index 7734123..496d258 100644
--- a/src/subscription_alert.rs
+++ b/src/subscription_alert.rs
@@ -68,7 +68,7 @@ impl From<SubscriptionAlert> for VNode {
 }
 
 /// Check if the result of the subscription check returned an active subscription
-pub fn subscription_is_active(result: &Option<Result<Value, Error>>) -> bool {
+pub fn subscription_is_active(result: Option<&Result<Value, Error>>) -> bool {
     match result {
         Some(Ok(data)) => {
             data["status"].as_str().map(|s| s.to_lowercase()).as_deref() == Some("active")
-- 
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] 15+ messages in thread

* [pdm-devel] [PATCH yew-comp 2/2] subscriptions: expose subscription_icon
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 15:23   ` [pdm-devel] applied: " Thomas Lamprecht
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active Dominik Csapak
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

we want to reuse this logic outside of proxmox-yew-comp too

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/lib.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/lib.rs b/src/lib.rs
index 8e43d35..6df8a32 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -187,7 +187,9 @@ mod subscription_panel;
 pub use subscription_panel::{ProxmoxSubscriptionPanel, SubscriptionPanel};
 
 mod subscription_info;
-pub use subscription_info::{subscription_note, ProxmoxSubscriptionInfo, SubscriptionInfo};
+pub use subscription_info::{
+    subscription_icon, subscription_note, ProxmoxSubscriptionInfo, SubscriptionInfo,
+};
 
 mod syslog;
 pub use syslog::{ProxmoxSyslog, Syslog};
-- 
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] 15+ messages in thread

* [pdm-devel] [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature Dominik Csapak
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 2/2] subscriptions: expose subscription_icon Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information Dominik Csapak
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

it takes an option of a reference, not a reference of an option

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 ui/src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ui/src/lib.rs b/ui/src/lib.rs
index 31068ab1..20dcec8b 100644
--- a/ui/src/lib.rs
+++ b/ui/src/lib.rs
@@ -241,7 +241,7 @@ pub(crate) fn locale_compare(first: String, second: &str, numeric: bool) -> std:
 /// Returns true if the global subscription checks succeeded
 pub async fn check_subscription() -> bool {
     let data: Result<Value, _> = http_get("/nodes/localhost/subscription", None).await;
-    proxmox_yew_comp::subscription_is_active(&Some(data))
+    proxmox_yew_comp::subscription_is_active(Some(&data))
 }
 
 /// Extract the version of a specific package from `RemoteUpdateSummary` for a specific node
-- 
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] 15+ messages in thread

* [pdm-devel] [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
                   ` (2 preceding siblings ...)
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel Dominik Csapak
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

so we can show that information on the subscription panel. This is
useful for users to see why the subscription is marked as invalid.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 lib/pdm-api-types/src/subscription.rs | 20 +++++++++++++++++++-
 server/src/api/nodes/subscription.rs  | 24 +++++++++++++-----------
 2 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/lib/pdm-api-types/src/subscription.rs b/lib/pdm-api-types/src/subscription.rs
index d38611e3..ca23b8e5 100644
--- a/lib/pdm-api-types/src/subscription.rs
+++ b/lib/pdm-api-types/src/subscription.rs
@@ -4,7 +4,7 @@ use anyhow::Error;
 use serde::{Deserialize, Serialize};
 
 use proxmox_schema::api;
-use proxmox_subscription::SubscriptionStatus;
+use proxmox_subscription::{SubscriptionInfo, SubscriptionStatus};
 
 #[api]
 // order is important here, since we use that for determining if a node has a valid subscription
@@ -156,3 +156,21 @@ pub struct SubscriptionStatistics {
     /// Total number of community level subscriptions across all remotes
     pub community: usize,
 }
+
+#[api(
+    properties: {
+        info: {
+            type: SubscriptionInfo,
+        }
+    }
+)]
+#[derive(Default, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(rename_all = "kebab-case")]
+/// The PDM subscription info
+pub struct PdmSubscriptionInfo {
+    #[serde(flatten)]
+    pub info: SubscriptionInfo,
+
+    /// PDM subscription statistics
+    pub statistics: SubscriptionStatistics,
+}
diff --git a/server/src/api/nodes/subscription.rs b/server/src/api/nodes/subscription.rs
index d9b44d59..d41a1794 100644
--- a/server/src/api/nodes/subscription.rs
+++ b/server/src/api/nodes/subscription.rs
@@ -11,7 +11,7 @@ use proxmox_sys::fs::CreateOptions;
 
 use pdm_api_types::remotes::RemoteType;
 use pdm_api_types::subscription::{
-    NodeSubscriptionInfo, SubscriptionLevel, SubscriptionStatistics,
+    NodeSubscriptionInfo, PdmSubscriptionInfo, SubscriptionLevel, SubscriptionStatistics,
 };
 use pdm_api_types::PRIV_SYS_MODIFY;
 
@@ -78,7 +78,7 @@ fn count_subscriptions(
     stats
 }
 
-fn check_counts(stats: SubscriptionStatistics) -> Result<(), Error> {
+fn check_counts(stats: &SubscriptionStatistics) -> Result<(), Error> {
     let subscribed_ratio = stats.active_subscriptions as f64 / stats.total_nodes as f64;
     let community_ratio = stats.community as f64 / stats.active_subscriptions as f64;
 
@@ -107,26 +107,28 @@ fn check_counts(stats: SubscriptionStatistics) -> Result<(), Error> {
     }
 )]
 /// Return subscription status
-pub async fn get_subscription() -> Result<SubscriptionInfo, Error> {
+pub async fn get_subscription() -> Result<PdmSubscriptionInfo, Error> {
     let infos = get_all_subscription_infos().await?;
 
-    let stats = count_subscriptions(&infos);
+    let statistics = count_subscriptions(&infos);
 
-    if let Err(err) = check_counts(stats) {
-        Ok(SubscriptionInfo {
+    let info = if let Err(err) = check_counts(&statistics) {
+        SubscriptionInfo {
             status: SubscriptionStatus::Invalid,
             message: Some(format!("{err}")),
             serverid: None,
             url: Some(PRODUCT_URL.into()),
             ..Default::default()
-        })
+        }
     } else {
-        Ok(SubscriptionInfo {
+        SubscriptionInfo {
             status: SubscriptionStatus::Active,
             url: Some(PRODUCT_URL.into()),
             ..Default::default()
-        })
-    }
+        }
+    };
+
+    Ok(PdmSubscriptionInfo { info, statistics })
 }
 
 #[api(
@@ -147,7 +149,7 @@ pub async fn check_subscription() -> Result<(), Error> {
     let infos = get_all_subscription_infos().await?;
     let stats = count_subscriptions(&infos);
 
-    if let Err(err) = check_counts(stats) {
+    if let Err(err) = check_counts(&stats) {
         update_apt_auth(APT_AUTH_FN, apt_auth_file_opts(), APT_AUTH_URL, None, None)?;
         return Err(err);
     }
-- 
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] 15+ messages in thread

* [pdm-devel] [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
                   ` (3 preceding siblings ...)
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 4/5] ui: show pdm subscription state in top nav bar Dominik Csapak
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

it's very similar to the pve/pbs/pmg one, but only shows relevant
information. It also shows the statistics that determines the validity
state.

Note: the thresholds and calculation is copied from the backend, to
further improve this, we should move that code somwhere we can reuse it
for both.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 ui/src/configuration/mod.rs                |   2 +
 ui/src/configuration/subscription_panel.rs | 187 +++++++++++++++++++++
 ui/src/main_menu.rs                        |  18 +-
 3 files changed, 206 insertions(+), 1 deletion(-)
 create mode 100644 ui/src/configuration/subscription_panel.rs

diff --git a/ui/src/configuration/mod.rs b/ui/src/configuration/mod.rs
index 35114336..18fc3966 100644
--- a/ui/src/configuration/mod.rs
+++ b/ui/src/configuration/mod.rs
@@ -13,6 +13,8 @@ mod permission_path_selector;
 mod webauthn;
 pub use webauthn::WebauthnPanel;
 
+pub mod subscription_panel;
+
 pub mod views;
 
 #[function_component(SystemConfiguration)]
diff --git a/ui/src/configuration/subscription_panel.rs b/ui/src/configuration/subscription_panel.rs
new file mode 100644
index 00000000..797eab0e
--- /dev/null
+++ b/ui/src/configuration/subscription_panel.rs
@@ -0,0 +1,187 @@
+use std::future::Future;
+use std::pin::Pin;
+use std::rc::Rc;
+
+use pdm_api_types::subscription::SubscriptionStatistics;
+use serde_json::Value;
+
+use yew::virtual_dom::{VComp, VNode};
+
+use pwt::prelude::*;
+use pwt::widget::{error_message, Button, Column, Container, Row, Toolbar};
+
+use proxmox_yew_comp::{http_get, http_post, KVGrid, KVGridRow};
+use proxmox_yew_comp::{LoadableComponent, LoadableComponentContext, LoadableComponentMaster};
+
+const SUBSCRIPTION_URL: &str = "/nodes/localhost/subscription";
+
+#[derive(Properties, PartialEq, Clone)]
+pub struct SubscriptionPanel {}
+
+impl SubscriptionPanel {
+    pub fn new() -> Self {
+        yew::props!(Self {})
+    }
+}
+
+pub enum Msg {
+    LoadFinished(Value),
+}
+
+pub struct ProxmoxSubscriptionPanel {
+    rows: Rc<Vec<KVGridRow>>,
+    data: Option<Rc<Value>>,
+}
+
+impl LoadableComponent for ProxmoxSubscriptionPanel {
+    type Message = Msg;
+    type Properties = SubscriptionPanel;
+    type ViewState = ();
+
+    fn create(_ctx: &LoadableComponentContext<Self>) -> Self {
+        Self {
+            rows: Rc::new(rows()),
+            data: None,
+        }
+    }
+
+    fn update(&mut self, _ctx: &LoadableComponentContext<Self>, msg: Self::Message) -> bool {
+        match msg {
+            Msg::LoadFinished(value) => {
+                self.data = Some(Rc::new(value));
+            }
+        }
+        true
+    }
+
+    fn load(
+        &self,
+        _ctx: &LoadableComponentContext<Self>,
+    ) -> Pin<Box<dyn Future<Output = Result<(), anyhow::Error>>>> {
+        let link = _ctx.link().clone();
+        Box::pin(async move {
+            let info = http_get(SUBSCRIPTION_URL, None).await?;
+            link.send_message(Msg::LoadFinished(info));
+            Ok(())
+        })
+    }
+
+    fn toolbar(&self, ctx: &LoadableComponentContext<Self>) -> Option<Html> {
+        let toolbar = Toolbar::new()
+            .class("pwt-overflow-hidden")
+            .border_bottom(true)
+            .with_child(
+                Button::new(tr!("Check"))
+                    .icon_class("fa fa-check-square-o")
+                    .on_activate({
+                        let link = ctx.link();
+
+                        move |_| {
+                            link.spawn({
+                                let link = link.clone();
+                                async move {
+                                    match http_post(SUBSCRIPTION_URL, None).await {
+                                        Ok(()) => link.send_reload(),
+                                        Err(err) => {
+                                            link.show_error(tr!("Error"), err.to_string(), true)
+                                        }
+                                    }
+                                }
+                            })
+                        }
+                    }),
+            )
+            .with_spacer()
+            .with_flex_spacer()
+            .with_child({
+                let loading = ctx.loading();
+                let link = ctx.link();
+                Button::refresh(loading).on_activate(move |_| link.send_reload())
+            });
+
+        Some(toolbar.into())
+    }
+
+    fn main_view(&self, _ctx: &LoadableComponentContext<Self>) -> Html {
+        let data = match &self.data {
+            Some(data) => data.clone(),
+            None => Rc::new(Value::Null),
+        };
+
+        KVGrid::new()
+            .class("pwt-flex-fit")
+            .data(data.clone())
+            .rows(Rc::clone(&self.rows))
+            .into()
+    }
+}
+
+impl From<SubscriptionPanel> for VNode {
+    fn from(val: SubscriptionPanel) -> Self {
+        let comp =
+            VComp::new::<LoadableComponentMaster<ProxmoxSubscriptionPanel>>(Rc::new(val), None);
+        VNode::from(comp)
+    }
+}
+
+// FIXME: ratios copied from backend
+
+// minimum ratio of nodes with active subscriptions
+const SUBSCRIPTION_THRESHOLD: f64 = 0.9;
+// max ratio of nodes with community subscriptions, among nodes with subscriptions
+const COMMUNITY_THRESHOLD: f64 = 0.4;
+
+fn rows() -> Vec<KVGridRow> {
+    vec![
+        KVGridRow::new("status", tr!("Status")).renderer(move |_name, value, record| {
+            let value = match value {
+                Value::String(data) => data,
+                Value::Null => return Container::from_tag("i").class("pwt-loading-icon").into(),
+                _ => return error_message(&tr!("invalid data")).into(),
+            };
+            match record["message"].as_str() {
+                Some(msg) => format!("{value}: {msg}").into(),
+                None => value.into(),
+            }
+        }),
+        KVGridRow::new("statistics", tr!("Statistics")).renderer(move |_name, value, _record| {
+            let statistics = serde_json::from_value::<SubscriptionStatistics>(value.clone());
+            match statistics {
+                Ok(stats) => {
+                    let subscribed_ratio =
+                        stats.active_subscriptions as f64 / stats.total_nodes as f64;
+                    let community_ratio =
+                        stats.community as f64 / stats.active_subscriptions as f64;
+
+                    fn operator(a: f64, b: f64) -> &'static str {
+                        if a >= b {
+                            ">="
+                        } else {
+                            "<"
+                        }
+                    }
+
+                    Column::new()
+                        .with_child(Row::new().with_child(tr!(
+                            "Subscribed Ratio: {0} ({1} {2})",
+                            format!("{:.0}%", subscribed_ratio * 100.0),
+                            operator(subscribed_ratio, SUBSCRIPTION_THRESHOLD),
+                            format!("{:.0}%", SUBSCRIPTION_THRESHOLD * 100.0),
+                        )))
+                        .with_child(Row::new().with_child(tr!(
+                            "Community Ratio: {0} ({1} {2})",
+                            format!("{:.0}%", community_ratio * 100.0),
+                            operator(community_ratio, COMMUNITY_THRESHOLD),
+                            format!("{:.0}%", COMMUNITY_THRESHOLD * 100.0),
+                        )))
+                        .into()
+                }
+                Err(err) => error_message(&format!("api error: {err}")).into(),
+            }
+        }),
+        KVGridRow::new("url", tr!("Info URL")).renderer(|_name, value, _record| {
+            let url = value.as_str().unwrap().to_string();
+            html! { <a target="_blank" href={url.clone()}>{url}</a> }
+        }),
+    ]
+}
diff --git a/ui/src/main_menu.rs b/ui/src/main_menu.rs
index 0847c7a2..18988eaf 100644
--- a/ui/src/main_menu.rs
+++ b/ui/src/main_menu.rs
@@ -7,13 +7,14 @@ use pwt::css::{self, Display, FlexFit};
 use pwt::prelude::*;
 use pwt::state::{NavigationContextExt, Selection};
 use pwt::widget::nav::{Menu, MenuItem, NavigationDrawer};
-use pwt::widget::{Container, Row, SelectionView, SelectionViewRenderInfo};
+use pwt::widget::{Container, Panel, Row, SelectionView, SelectionViewRenderInfo};
 
 use proxmox_yew_comp::{AclContext, NotesView, XTermJs};
 
 use pdm_api_types::remotes::RemoteType;
 use pdm_api_types::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
 
+use crate::configuration::subscription_panel::SubscriptionPanel;
 use crate::configuration::views::ViewGrid;
 use crate::dashboard::view::View;
 use crate::remotes::RemotesPanel;
@@ -266,6 +267,21 @@ impl Component for PdmMainMenu {
             |_| html! {<CertificatesPanel/>},
         );
 
+        register_view(
+            &mut config_submenu,
+            &mut content,
+            tr!("Subscription"),
+            "subscription",
+            Some("fa fa-support"),
+            |_| {
+                Panel::new()
+                    .class(css::FlexFit)
+                    .title(tr!("Subscription"))
+                    .with_child(SubscriptionPanel::new())
+                    .into()
+            },
+        );
+
         register_submenu(
             &mut menu,
             &mut content,
-- 
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] 15+ messages in thread

* [pdm-devel] [PATCH datacenter-manager 4/5] ui: show pdm subscription state in top nav bar
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
                   ` (4 preceding siblings ...)
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore Dominik Csapak
  2025-12-02 15:27 ` [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Thomas Lamprecht
  7 siblings, 0 replies; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: 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 <d.csapak@proxmox.com>
---
 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<RemoteList, Error>;
@@ -40,12 +41,14 @@ enum Msg {
     RemoteList(MsgRemoteList),
     ViewList(MsgViewList),
     UpdateViewList,
+    UpdateSubscriptionInfo(Result<Value, Error>, bool), // fresh login
 }
 
 struct DatacenterManagerApp {
     _auth_observer: AuthObserver,
     login_info: Option<Authentication>,
     subscription_confirmed: bool,
+    subscription: Option<PdmSubscriptionInfo>,
     show_subscription_alert: Option<bool>,
     running_tasks: Loader<Vec<TaskListItem>>,
     running_tasks_timeout: Option<Timeout>,
@@ -74,21 +77,12 @@ impl DatacenterManagerApp {
     fn on_login(&mut self, ctx: &Context<Self>, 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<Self>, 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::<PdmSubscriptionInfo>(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<VersionInfo, Error> {
 pub struct TopNavBar {
     running_tasks: Loader<Vec<TaskListItem>>,
 
+    #[builder(IntoPropValue, into_prop_value)]
+    #[prop_or_default]
+    /// Used to show the subscription validity
+    subscription_info: Option<PdmSubscriptionInfo>,
+
     #[builder_cb(IntoEventCallback, into_event_callback, ())]
     #[prop_or_default]
     pub on_logout: Option<Callback<()>>,
@@ -284,6 +293,18 @@ impl Component for PdmTopNavBar {
                     <a href="https://bugzilla.proxmox.com" target="_blank">{"BETA"}</a>
                 </span>
             })
+            .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<TopNavBar> for VNode {
         VNode::from(comp)
     }
 }
+
+fn show_subscription_notice(subscriptions: Option<PdmSubscriptionInfo>) -> 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


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
                   ` (5 preceding siblings ...)
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 4/5] ui: show pdm subscription state in top nav bar Dominik Csapak
@ 2025-12-02 14:31 ` Dominik Csapak
  2025-12-03 12:08   ` Thomas Lamprecht
  2025-12-02 15:27 ` [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Thomas Lamprecht
  7 siblings, 1 reply; 15+ messages in thread
From: Dominik Csapak @ 2025-12-02 14:31 UTC (permalink / raw)
  To: pdm-devel

Since we now show the subscription state of pdm always in the top bar,
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] 15+ messages in thread

* [pdm-devel] applied: [PATCH yew-comp 1/2] subscription check: use more useful function signature
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature Dominik Csapak
@ 2025-12-02 15:23   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 15:23 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:02 +0100, Dominik Csapak wrote:
> having a reference of an option is very unweildly at times, e.g. when
> having the inner type, it's necessary to move it into an option, even if
> `subscription_is_active` does not need to own the data.
> 
> using an option of a reference makes usage much more ergonomic at times.
> 
> 
> [...]

Applied, thanks!

[1/2] subscription check: use more useful function signature
      commit: 9a4b3955cae317d1ab7d1c64e17530295acab317


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] applied: [PATCH yew-comp 2/2] subscriptions: expose subscription_icon
  2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 2/2] subscriptions: expose subscription_icon Dominik Csapak
@ 2025-12-02 15:23   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 15:23 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:03 +0100, Dominik Csapak wrote:
> we want to reuse this logic outside of proxmox-yew-comp too
> 
> 

Applied, thanks!

[2/2] subscriptions: expose subscription_icon
      commit: 2c8470e16da7b87a98c979c7f1ac212a69d4c972


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel
  2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
                   ` (6 preceding siblings ...)
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore Dominik Csapak
@ 2025-12-02 15:27 ` Thomas Lamprecht
  7 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 15:27 UTC (permalink / raw)
  To: Proxmox Datacenter Manager development discussion, Dominik Csapak

Am 02.12.25 um 15:32 schrieb Dominik Csapak:
> This adds a dedicated subscription panel for pdm, and adds the overall subscription
> state to the top nav bar.

Thx, will take a look.

> 
> This means we can drop the required subscription panel for the views.
> 
> I opted for not removing the subscription panel from the default dashboard,
> but if that's wanted it is not a big change.

good call! let's keep that.

> 
> Note that the first proxmox-yew-comp patch breaks current pdm, since a
> public function signature changes.

That change does make ergonomically sense IMO.


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] applied: [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active Dominik Csapak
@ 2025-12-02 16:13   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 16:13 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:04 +0100, Dominik Csapak wrote:
> it takes an option of a reference, not a reference of an option
> 
> 

Applied, thanks!

[1/5] ui: adapt to signature change of subscription_is_active
      commit: 75f5708be57f717c0888f7683b8c2fa7b6d7844f


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] applied: [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information Dominik Csapak
@ 2025-12-02 16:13   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 16:13 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:05 +0100, Dominik Csapak wrote:
> so we can show that information on the subscription panel. This is
> useful for users to see why the subscription is marked as invalid.
> 
> 

Applied, thanks!

[2/5] lib/server: include subscription statistics in subscription information
      commit: 1e081f55660010bd080ab083b9a48b0d02d03308


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pdm-devel] applied: [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel Dominik Csapak
@ 2025-12-02 16:13   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-02 16:13 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:06 +0100, Dominik Csapak wrote:
> it's very similar to the pve/pbs/pmg one, but only shows relevant
> information. It also shows the statistics that determines the validity
> state.
> 
> Note: the thresholds and calculation is copied from the backend, to
> further improve this, we should move that code somwhere we can reuse it
> for both.
> 
> [...]

Applied, thanks!

[3/5] ui: configuration: add subscription panel
      commit: eab22eabf390964b575a063bddc4b29ae2971e1b


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore
  2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore Dominik Csapak
@ 2025-12-03 12:08   ` Thomas Lamprecht
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Lamprecht @ 2025-12-03 12:08 UTC (permalink / raw)
  To: pdm-devel, Dominik Csapak

On Tue, 02 Dec 2025 15:31:08 +0100, Dominik Csapak wrote:
> Since we now show the subscription state of pdm always in the top bar,
> the subscription panel in views are useful, but not required anymore.
> 
> 

Applied, thanks!

[5/5] ui: views: make Subscription panel not required anymore
      commit: 65a4edaa299bce5b1430c3c587638373defb10a3


_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-12-03 12:08 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02 14:31 [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Dominik Csapak
2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 1/2] subscription check: use more useful function signature Dominik Csapak
2025-12-02 15:23   ` [pdm-devel] applied: " Thomas Lamprecht
2025-12-02 14:31 ` [pdm-devel] [PATCH yew-comp 2/2] subscriptions: expose subscription_icon Dominik Csapak
2025-12-02 15:23   ` [pdm-devel] applied: " Thomas Lamprecht
2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 1/5] ui: adapt to signature change of subscription_is_active Dominik Csapak
2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 2/5] lib/server: include subscription statistics in subscription information Dominik Csapak
2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 3/5] ui: configuration: add subscription panel Dominik Csapak
2025-12-02 16:13   ` [pdm-devel] applied: " Thomas Lamprecht
2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 4/5] ui: show pdm subscription state in top nav bar Dominik Csapak
2025-12-02 14:31 ` [pdm-devel] [PATCH datacenter-manager 5/5] ui: views: make Subscription panel not required anymore Dominik Csapak
2025-12-03 12:08   ` Thomas Lamprecht
2025-12-02 15:27 ` [pdm-devel] [PATCH datacenter-manager/yew-comp 0/7] add top bar subscription state and dedicated panel Thomas Lamprecht

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal