* [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp
@ 2025-12-18 9:51 Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule Lukas Wagner
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 9:51 UTC (permalink / raw)
To: pdm-devel
proxmox-yew-comp:
Lukas Wagner (2):
utils: move task descriptions to a submodule
task descriptions: add PBS task descriptions
src/utils/mod.rs | 228 +------------------
src/utils/task_descriptions.rs | 400 +++++++++++++++++++++++++++++++++
2 files changed, 412 insertions(+), 216 deletions(-)
create mode 100644 src/utils/task_descriptions.rs
proxmox-datacenter-manager:
Lukas Wagner (2):
ui: register task descriptions for some native PDM tasks
ui: use task descriptions from yew-comp for PBS and PVE
ui/src/lib.rs | 2 +-
ui/src/main.rs | 7 +--
ui/src/tasks.rs | 122 ++++++++----------------------------------------
3 files changed, 25 insertions(+), 106 deletions(-)
Summary over all repositories:
5 files changed, 437 insertions(+), 322 deletions(-)
--
Generated by murpp 0.9.0
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
@ 2025-12-18 9:51 ` Lukas Wagner
2025-12-18 11:49 ` Dominik Csapak
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions Lukas Wagner
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 9:51 UTC (permalink / raw)
To: pdm-devel
No functional changes. Reexports from the 'utils' module ensure that
clients don't have to change.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/utils/mod.rs | 228 ++-------------------------------
src/utils/task_descriptions.rs | 214 +++++++++++++++++++++++++++++++
2 files changed, 226 insertions(+), 216 deletions(-)
create mode 100644 src/utils/task_descriptions.rs
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 856297f..600e436 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,6 +1,4 @@
use std::collections::HashMap;
-use std::fmt::Display;
-use std::sync::Mutex;
use percent_encoding::percent_decode;
use serde_json::Value;
@@ -11,9 +9,13 @@ use crate::common_api_types::ProxmoxUpid;
use pwt::tr;
mod clipboard;
+mod task_descriptions;
+
#[allow(deprecated)]
pub use clipboard::{copy_text_to_clipboard, copy_to_clipboard};
+pub use task_descriptions::*;
+
/// Somewhat like a human would tell durations, omit zero values and do not
/// give seconds precision if we talk days already
pub fn format_duration_human(ut: f64) -> String {
@@ -154,122 +156,6 @@ pub fn epoch_to_input_value(epoch: i64) -> String {
}
}
-// todo: we want to use Fn(&str, Option<&str>),
-#[allow(clippy::type_complexity)]
-static TASK_DESCR_TABLE: Mutex<
- Option<HashMap<String, Box<dyn Send + Sync + Fn(String, Option<String>) -> String>>>,
-> = Mutex::new(None);
-
-pub trait IntoTaskDescriptionRenderFn {
- fn into_task_description_render_fn(
- self,
- ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String>;
-}
-
-impl<F: 'static + Send + Sync + Fn(String, Option<String>) -> String> IntoTaskDescriptionRenderFn
- for F
-{
- fn into_task_description_render_fn(
- self,
- ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String> {
- Box::new(self)
- }
-}
-
-impl<A: Display, B: Display> IntoTaskDescriptionRenderFn for (A, B) {
- fn into_task_description_render_fn(
- self,
- ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
- let task_type = self.0.to_string();
- let action = self.1.to_string();
- Box::new(move |_, id| {
- format!(
- "{} {} {}",
- task_type,
- id.as_deref().unwrap_or("unknown"),
- action
- )
- })
- }
-}
-
-impl IntoTaskDescriptionRenderFn for String {
- fn into_task_description_render_fn(
- self,
- ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
- Box::new(move |_, _id| self.clone())
- }
-}
-
-pub fn register_task_description(
- name: impl Into<String>,
- render: impl IntoTaskDescriptionRenderFn,
-) {
- let mut map = TASK_DESCR_TABLE.lock().unwrap();
- if map.is_none() {
- *map = Some(HashMap::new());
- }
-
- let map = map.as_mut().unwrap();
-
- let name: String = name.into();
- let render = render.into_task_description_render_fn();
-
- map.insert(name, render);
-}
-
-pub fn lookup_task_description(name: &str, id: Option<&str>) -> Option<String> {
- let map = TASK_DESCR_TABLE.lock().unwrap();
- match *map {
- Some(ref map) => map
- .get(name)
- .map(|function| function(name.to_string(), id.map(|id| id.to_string()))),
- None => None,
- }
-}
-
-pub fn registered_task_types() -> Vec<String> {
- let map = TASK_DESCR_TABLE.lock().unwrap();
- match *map {
- Some(ref map) => map.keys().map(|t| t.to_string()).collect(),
- None => Vec::new(),
- }
-}
-
-pub fn init_task_descr_table_base() {
- register_task_description("aptupdate", tr!("Update package database"));
- // TRANSLATORS: Spice is a proper name, see https://www.spice-space.org
- register_task_description("spiceshell", tr!("Shell (Spice)"));
- register_task_description("vncshell", tr!("Shell (VNC)"));
- register_task_description("termproxy", tr!("Console (xterm.js)"));
-
- register_task_description("diskinit", (tr!("Disk"), tr!("Initialize Disk with GPT")));
- register_task_description("srvstart", (tr!("Service"), tr!("Start")));
- register_task_description("srvstop", (tr!("Service"), tr!("Stop")));
- register_task_description("srvrestart", (tr!("Service"), tr!("Restart")));
- register_task_description("srvreload", (tr!("Service"), tr!("Reload")));
-}
-
-/// Uses information from the given `UPID` to render the task description with [`format_task_description`]
-pub fn format_upid(upid: &str) -> String {
- match upid.parse::<ProxmoxUpid>() {
- Err(_) => upid.to_string(),
- Ok(upid) => format_task_description(&upid.worker_type, upid.worker_id.as_deref()),
- }
-}
-
-/// Formats the given worker type and id to a Human readable task description
-pub fn format_task_description(worker_type: &str, worker_id: Option<&str>) -> String {
- if let Some(text) = lookup_task_description(worker_type, worker_id) {
- text
- } else {
- match worker_id {
- Some(id) => format!("{} {}", worker_type, id),
- None => worker_type.to_string(),
- }
- }
-}
-
pub struct AuthDomainInfo {
pub ty: String, // type
//pub description: String,
@@ -349,104 +235,14 @@ pub fn set_location_href(href: &str) {
let _ = location.set_href(href);
}
-/// Register PVE task descriptions
-pub fn register_pve_tasks() {
- register_task_description("qmstart", ("VM", tr!("Start")));
- register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
- register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
- register_task_description("acmerefresh", ("ACME Account", tr!("Refresh")));
- register_task_description("acmeregister", ("ACME Account", tr!("Register")));
- register_task_description("acmerenew", ("SRV", tr!("Renew Certificate")));
- register_task_description("acmerevoke", ("SRV", tr!("Revoke Certificate")));
- register_task_description("acmeupdate", ("ACME Account", tr!("Update")));
- register_task_description("auth-realm-sync", (tr!("Realm"), tr!("Sync")));
- register_task_description("auth-realm-sync-test", (tr!("Realm"), tr!("Sync Preview")));
- register_task_description("cephcreatemds", ("Ceph Metadata Server", tr!("Create")));
- register_task_description("cephcreatemgr", ("Ceph Manager", tr!("Create")));
- register_task_description("cephcreatemon", ("Ceph Monitor", tr!("Create")));
- register_task_description("cephcreateosd", ("Ceph OSD", tr!("Create")));
- register_task_description("cephcreatepool", ("Ceph Pool", tr!("Create")));
- register_task_description("cephdestroymds", ("Ceph Metadata Server", tr!("Destroy")));
- register_task_description("cephdestroymgr", ("Ceph Manager", tr!("Destroy")));
- register_task_description("cephdestroymon", ("Ceph Monitor", tr!("Destroy")));
- register_task_description("cephdestroyosd", ("Ceph OSD", tr!("Destroy")));
- register_task_description("cephdestroypool", ("Ceph Pool", tr!("Destroy")));
- register_task_description("cephdestroyfs", ("CephFS", tr!("Destroy")));
- register_task_description("cephfscreate", ("CephFS", tr!("Create")));
- register_task_description("cephsetpool", ("Ceph Pool", tr!("Edit")));
- register_task_description("cephsetflags", tr!("Change global Ceph flags"));
- register_task_description("clustercreate", tr!("Create Cluster"));
- register_task_description("clusterjoin", tr!("Join Cluster"));
- register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
- register_task_description("dirremove", (tr!("Directory"), tr!("Remove")));
- register_task_description("download", (tr!("File"), tr!("Download")));
- register_task_description("hamigrate", ("HA", tr!("Migrate")));
- register_task_description("hashutdown", ("HA", tr!("Shutdown")));
- register_task_description("hastart", ("HA", tr!("Start")));
- register_task_description("hastop", ("HA", tr!("Stop")));
- register_task_description("imgcopy", tr!("Copy data"));
- register_task_description("imgdel", tr!("Erase data"));
- register_task_description("lvmcreate", (tr!("LVM Storage"), tr!("Create")));
- register_task_description("lvmremove", ("Volume Group", tr!("Remove")));
- register_task_description("lvmthincreate", (tr!("LVM-Thin Storage"), tr!("Create")));
- register_task_description("lvmthinremove", ("Thinpool", tr!("Remove")));
- register_task_description("migrateall", tr!("Bulk migrate VMs and Containers"));
- register_task_description("move_volume", ("CT", tr!("Move Volume")));
- register_task_description("pbs-download", ("VM/CT", tr!("File Restore Download")));
- register_task_description("pull_file", ("CT", tr!("Pull file")));
- register_task_description("push_file", ("CT", tr!("Push file")));
- register_task_description("qmclone", ("VM", tr!("Clone")));
- register_task_description("qmconfig", ("VM", tr!("Configure")));
- register_task_description("qmcreate", ("VM", tr!("Create")));
- register_task_description("qmdelsnapshot", ("VM", tr!("Delete Snapshot")));
- register_task_description("qmdestroy", ("VM", tr!("Destroy")));
- register_task_description("qmigrate", ("VM", tr!("Migrate")));
- register_task_description("qmmove", ("VM", tr!("Move disk")));
- register_task_description("qmpause", ("VM", tr!("Pause")));
- register_task_description("qmreboot", ("VM", tr!("Reboot")));
- register_task_description("qmreset", ("VM", tr!("Reset")));
- register_task_description("qmrestore", ("VM", tr!("Restore")));
- register_task_description("qmresume", ("VM", tr!("Resume")));
- register_task_description("qmrollback", ("VM", tr!("Rollback")));
- register_task_description("qmshutdown", ("VM", tr!("Shutdown")));
- register_task_description("qmsnapshot", ("VM", tr!("Snapshot")));
- register_task_description("qmstart", ("VM", tr!("Start")));
- register_task_description("qmstop", ("VM", tr!("Stop")));
- register_task_description("qmsuspend", ("VM", tr!("Hibernate")));
- register_task_description("qmtemplate", ("VM", tr!("Convert to template")));
- register_task_description("resize", ("VM/CT", tr!("Resize")));
- register_task_description("spiceproxy", ("VM/CT", tr!("Console") + " (Spice)"));
- register_task_description("spiceshell", tr!("Shell") + " (Spice)");
- register_task_description("startall", tr!("Bulk start VMs and Containers"));
- register_task_description("stopall", tr!("Bulk shutdown VMs and Containers"));
- register_task_description("suspendall", tr!("Suspend all VMs"));
- register_task_description("unknownimgdel", tr!("Destroy image from unknown guest"));
- register_task_description("wipedisk", ("Device", tr!("Wipe Disk")));
- register_task_description("vncproxy", ("VM/CT", tr!("Console")));
- register_task_description("vncshell", tr!("Shell"));
- register_task_description("vzclone", ("CT", tr!("Clone")));
- register_task_description("vzcreate", ("CT", tr!("Create")));
- register_task_description("vzdelsnapshot", ("CT", tr!("Delete Snapshot")));
- register_task_description("vzdestroy", ("CT", tr!("Destroy")));
- register_task_description("vzdump", |_ty, id| match id {
- Some(id) => format!("VM/CT {id} - {}", tr!("Backup")),
- None => tr!("Backup Job"),
- });
- register_task_description("vzmigrate", ("CT", tr!("Migrate")));
- register_task_description("vzmount", ("CT", tr!("Mount")));
- register_task_description("vzreboot", ("CT", tr!("Reboot")));
- register_task_description("vzrestore", ("CT", tr!("Restore")));
- register_task_description("vzresume", ("CT", tr!("Resume")));
- register_task_description("vzrollback", ("CT", tr!("Rollback")));
- register_task_description("vzshutdown", ("CT", tr!("Shutdown")));
- register_task_description("vzsnapshot", ("CT", tr!("Snapshot")));
- register_task_description("vzstart", ("CT", tr!("Start")));
- register_task_description("vzstop", ("CT", tr!("Stop")));
- register_task_description("vzsuspend", ("CT", tr!("Suspend")));
- register_task_description("vztemplate", ("CT", tr!("Convert to template")));
- register_task_description("vzumount", ("CT", tr!("Unmount")));
- register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
- register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
+/// Uses information from the given `UPID` to render the task description with [`format_task_description`]
+pub fn format_upid(upid: &str) -> String {
+ match upid.parse::<ProxmoxUpid>() {
+ Err(_) => upid.to_string(),
+ Ok(upid) => {
+ task_descriptions::format_task_description(&upid.worker_type, upid.worker_id.as_deref())
+ }
+ }
}
pub fn openid_redirection_authorization() -> Option<HashMap<String, String>> {
diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
new file mode 100644
index 0000000..86525a4
--- /dev/null
+++ b/src/utils/task_descriptions.rs
@@ -0,0 +1,214 @@
+use std::{collections::HashMap, fmt::Display, sync::Mutex};
+
+use pwt::tr;
+
+// todo: we want to use Fn(&str, Option<&str>),
+#[allow(clippy::type_complexity)]
+static TASK_DESCR_TABLE: Mutex<
+ Option<HashMap<String, Box<dyn Send + Sync + Fn(String, Option<String>) -> String>>>,
+> = Mutex::new(None);
+
+pub trait IntoTaskDescriptionRenderFn {
+ fn into_task_description_render_fn(
+ self,
+ ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String>;
+}
+
+impl<F: 'static + Send + Sync + Fn(String, Option<String>) -> String> IntoTaskDescriptionRenderFn
+ for F
+{
+ fn into_task_description_render_fn(
+ self,
+ ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String> {
+ Box::new(self)
+ }
+}
+
+impl<A: Display, B: Display> IntoTaskDescriptionRenderFn for (A, B) {
+ fn into_task_description_render_fn(
+ self,
+ ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
+ let task_type = self.0.to_string();
+ let action = self.1.to_string();
+ Box::new(move |_, id| {
+ format!(
+ "{} {} {}",
+ task_type,
+ id.as_deref().unwrap_or("unknown"),
+ action
+ )
+ })
+ }
+}
+
+impl IntoTaskDescriptionRenderFn for String {
+ fn into_task_description_render_fn(
+ self,
+ ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
+ Box::new(move |_, _id| self.clone())
+ }
+}
+
+pub fn register_task_description(
+ name: impl Into<String>,
+ render: impl IntoTaskDescriptionRenderFn,
+) {
+ let mut map = TASK_DESCR_TABLE.lock().unwrap();
+ if map.is_none() {
+ *map = Some(HashMap::new());
+ }
+
+ let map = map.as_mut().unwrap();
+
+ let name: String = name.into();
+ let render = render.into_task_description_render_fn();
+
+ map.insert(name, render);
+}
+
+pub fn lookup_task_description(name: &str, id: Option<&str>) -> Option<String> {
+ let map = TASK_DESCR_TABLE.lock().unwrap();
+ match *map {
+ Some(ref map) => map
+ .get(name)
+ .map(|function| function(name.to_string(), id.map(|id| id.to_string()))),
+ None => None,
+ }
+}
+
+pub fn registered_task_types() -> Vec<String> {
+ let map = TASK_DESCR_TABLE.lock().unwrap();
+ match *map {
+ Some(ref map) => map.keys().map(|t| t.to_string()).collect(),
+ None => Vec::new(),
+ }
+}
+
+pub fn init_task_descr_table_base() {
+ register_task_description("aptupdate", tr!("Update package database"));
+ // TRANSLATORS: Spice is a proper name, see https://www.spice-space.org
+ register_task_description("spiceshell", tr!("Shell (Spice)"));
+ register_task_description("vncshell", tr!("Shell (VNC)"));
+ register_task_description("termproxy", tr!("Console (xterm.js)"));
+
+ register_task_description("diskinit", (tr!("Disk"), tr!("Initialize Disk with GPT")));
+ register_task_description("srvstart", (tr!("Service"), tr!("Start")));
+ register_task_description("srvstop", (tr!("Service"), tr!("Stop")));
+ register_task_description("srvrestart", (tr!("Service"), tr!("Restart")));
+ register_task_description("srvreload", (tr!("Service"), tr!("Reload")));
+}
+
+/// Formats the given worker type and id to a Human readable task description
+pub fn format_task_description(worker_type: &str, worker_id: Option<&str>) -> String {
+ if let Some(text) = lookup_task_description(worker_type, worker_id) {
+ text
+ } else {
+ match worker_id {
+ Some(id) => format!("{} {}", worker_type, id),
+ None => worker_type.to_string(),
+ }
+ }
+}
+
+/// Register PVE task descriptions
+pub fn register_pve_tasks() {
+ register_task_description("qmstart", ("VM", tr!("Start")));
+ register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
+ register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
+ register_task_description("acmerefresh", ("ACME Account", tr!("Refresh")));
+ register_task_description("acmeregister", ("ACME Account", tr!("Register")));
+ register_task_description("acmerenew", ("SRV", tr!("Renew Certificate")));
+ register_task_description("acmerevoke", ("SRV", tr!("Revoke Certificate")));
+ register_task_description("acmeupdate", ("ACME Account", tr!("Update")));
+ register_task_description("auth-realm-sync", (tr!("Realm"), tr!("Sync")));
+ register_task_description("auth-realm-sync-test", (tr!("Realm"), tr!("Sync Preview")));
+ register_task_description("cephcreatemds", ("Ceph Metadata Server", tr!("Create")));
+ register_task_description("cephcreatemgr", ("Ceph Manager", tr!("Create")));
+ register_task_description("cephcreatemon", ("Ceph Monitor", tr!("Create")));
+ register_task_description("cephcreateosd", ("Ceph OSD", tr!("Create")));
+ register_task_description("cephcreatepool", ("Ceph Pool", tr!("Create")));
+ register_task_description("cephdestroymds", ("Ceph Metadata Server", tr!("Destroy")));
+ register_task_description("cephdestroymgr", ("Ceph Manager", tr!("Destroy")));
+ register_task_description("cephdestroymon", ("Ceph Monitor", tr!("Destroy")));
+ register_task_description("cephdestroyosd", ("Ceph OSD", tr!("Destroy")));
+ register_task_description("cephdestroypool", ("Ceph Pool", tr!("Destroy")));
+ register_task_description("cephdestroyfs", ("CephFS", tr!("Destroy")));
+ register_task_description("cephfscreate", ("CephFS", tr!("Create")));
+ register_task_description("cephsetpool", ("Ceph Pool", tr!("Edit")));
+ register_task_description("cephsetflags", tr!("Change global Ceph flags"));
+ register_task_description("clustercreate", tr!("Create Cluster"));
+ register_task_description("clusterjoin", tr!("Join Cluster"));
+ register_task_description("create_zone", tr!("Create EVPN Zone"));
+ register_task_description("create_vnet", tr!("Create EVPN VNet"));
+ register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
+ register_task_description("dirremove", (tr!("Directory"), tr!("Remove")));
+ register_task_description("download", (tr!("File"), tr!("Download")));
+ register_task_description("hamigrate", ("HA", tr!("Migrate")));
+ register_task_description("hashutdown", ("HA", tr!("Shutdown")));
+ register_task_description("hastart", ("HA", tr!("Start")));
+ register_task_description("hastop", ("HA", tr!("Stop")));
+ register_task_description("imgcopy", tr!("Copy data"));
+ register_task_description("imgdel", tr!("Erase data"));
+ register_task_description("lvmcreate", (tr!("LVM Storage"), tr!("Create")));
+ register_task_description("lvmremove", ("Volume Group", tr!("Remove")));
+ register_task_description("lvmthincreate", (tr!("LVM-Thin Storage"), tr!("Create")));
+ register_task_description("lvmthinremove", ("Thinpool", tr!("Remove")));
+ register_task_description("migrateall", tr!("Bulk migrate VMs and Containers"));
+ register_task_description("move_volume", ("CT", tr!("Move Volume")));
+ register_task_description("pbs-download", ("VM/CT", tr!("File Restore Download")));
+ register_task_description("pull_file", ("CT", tr!("Pull file")));
+ register_task_description("push_file", ("CT", tr!("Push file")));
+ register_task_description("qmclone", ("VM", tr!("Clone")));
+ register_task_description("qmconfig", ("VM", tr!("Configure")));
+ register_task_description("qmcreate", ("VM", tr!("Create")));
+ register_task_description("qmdelsnapshot", ("VM", tr!("Delete Snapshot")));
+ register_task_description("qmdestroy", ("VM", tr!("Destroy")));
+ register_task_description("qmigrate", ("VM", tr!("Migrate")));
+ register_task_description("qmmove", ("VM", tr!("Move disk")));
+ register_task_description("qmpause", ("VM", tr!("Pause")));
+ register_task_description("qmreboot", ("VM", tr!("Reboot")));
+ register_task_description("qmreset", ("VM", tr!("Reset")));
+ register_task_description("qmrestore", ("VM", tr!("Restore")));
+ register_task_description("qmresume", ("VM", tr!("Resume")));
+ register_task_description("qmrollback", ("VM", tr!("Rollback")));
+ register_task_description("qmshutdown", ("VM", tr!("Shutdown")));
+ register_task_description("qmsnapshot", ("VM", tr!("Snapshot")));
+ register_task_description("qmstart", ("VM", tr!("Start")));
+ register_task_description("qmstop", ("VM", tr!("Stop")));
+ register_task_description("qmsuspend", ("VM", tr!("Hibernate")));
+ register_task_description("qmtemplate", ("VM", tr!("Convert to template")));
+ register_task_description("reloadnetworkall", tr!("Apply SDN configuration"));
+ register_task_description("resize", ("VM/CT", tr!("Resize")));
+ register_task_description("spiceproxy", ("VM/CT", tr!("Console") + " (Spice)"));
+ register_task_description("spiceshell", tr!("Shell") + " (Spice)");
+ register_task_description("startall", tr!("Bulk start VMs and Containers"));
+ register_task_description("stopall", tr!("Bulk shutdown VMs and Containers"));
+ register_task_description("suspendall", tr!("Suspend all VMs"));
+ register_task_description("unknownimgdel", tr!("Destroy image from unknown guest"));
+ register_task_description("wipedisk", ("Device", tr!("Wipe Disk")));
+ register_task_description("vncproxy", ("VM/CT", tr!("Console")));
+ register_task_description("vncshell", tr!("Shell"));
+ register_task_description("vzclone", ("CT", tr!("Clone")));
+ register_task_description("vzcreate", ("CT", tr!("Create")));
+ register_task_description("vzdelsnapshot", ("CT", tr!("Delete Snapshot")));
+ register_task_description("vzdestroy", ("CT", tr!("Destroy")));
+ register_task_description("vzdump", |_ty, id| match id {
+ Some(id) => format!("VM/CT {id} - {}", tr!("Backup")),
+ None => tr!("Backup Job"),
+ });
+ register_task_description("vzmigrate", ("CT", tr!("Migrate")));
+ register_task_description("vzmount", ("CT", tr!("Mount")));
+ register_task_description("vzreboot", ("CT", tr!("Reboot")));
+ register_task_description("vzrestore", ("CT", tr!("Restore")));
+ register_task_description("vzresume", ("CT", tr!("Resume")));
+ register_task_description("vzrollback", ("CT", tr!("Rollback")));
+ register_task_description("vzshutdown", ("CT", tr!("Shutdown")));
+ register_task_description("vzsnapshot", ("CT", tr!("Snapshot")));
+ register_task_description("vzstart", ("CT", tr!("Start")));
+ register_task_description("vzstop", ("CT", tr!("Stop")));
+ register_task_description("vzsuspend", ("CT", tr!("Suspend")));
+ register_task_description("vztemplate", ("CT", tr!("Convert to template")));
+ register_task_description("vzumount", ("CT", tr!("Unmount")));
+ register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
+ register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
+}
--
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] 11+ messages in thread
* [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule Lukas Wagner
@ 2025-12-18 9:51 ` Lukas Wagner
2025-12-18 12:19 ` Dominik Csapak
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 1/2] ui: register task descriptions for some native PDM tasks Lukas Wagner
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 9:51 UTC (permalink / raw)
To: pdm-devel
Tried to make these match the JS ones as closely as possible. Some of
these could be improved in the future, but this should then be done in
tandem with the JS definitions.
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
src/utils/task_descriptions.rs | 186 +++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
index 86525a4..caeb563 100644
--- a/src/utils/task_descriptions.rs
+++ b/src/utils/task_descriptions.rs
@@ -212,3 +212,189 @@ pub fn register_pve_tasks() {
register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
}
+
+/// Register PBS task descriptions.
+pub fn register_pbs_tasks() {
+ register_task_description("acme-deativate", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Deactivate ACME Account - {0}", id)
+ });
+ register_task_description("acme-register", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Register ACME Account - {0}", id)
+ });
+ register_task_description("acme-update", |_ty, id: Option<String>| {
+ let id = id.unwrap_or_else(|| "default".to_string());
+ tr!("Update ACME Account - {0}", id)
+ });
+ register_task_description("acme-new-cert", ("", tr!("Order Certificate")));
+ register_task_description("acme-renew-cert", ("", tr!("Renew Certificate")));
+ register_task_description("acme-revoke-cert", ("", tr!("Revoke Certificate")));
+ register_task_description("backup", |_ty, id: Option<String>| {
+ render_datastore_worker_id(id, &tr!("Backup"))
+ });
+ register_task_description(
+ "barcode-label-media",
+ (tr!("Drive"), tr!("Barcode-Label Media")),
+ );
+ register_task_description("catalog-media", (tr!("Drive"), tr!("Catalog Media")));
+ register_task_description(
+ "create-datastore",
+ (tr!("Datastore"), tr!("Create Datastore")),
+ );
+ register_task_description(
+ "delete-datastore",
+ (tr!("Datastore"), tr!("Remove Datastore")),
+ );
+ register_task_description(
+ "delete-namespace",
+ (tr!("Namespace"), tr!("Remove Namespace")),
+ );
+ register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
+ register_task_description("dirremove", (tr!("Directory Storage"), tr!("Remove")));
+ register_task_description("eject-media", (tr!("Drive"), tr!("Eject Media")));
+ register_task_description("format-media", (tr!("Drive"), tr!("Format Media")));
+ register_task_description("forget-group", (tr!("Group"), tr!("Remove Group")));
+ register_task_description(
+ "garbage_collection",
+ (tr!("Datastore"), tr!("Garbage Collect")),
+ );
+ register_task_description("realm-sync", ("Realm", tr!("User Sync")));
+ register_task_description("inventory-update", (tr!("Drive"), tr!("Inventory Update")));
+ register_task_description("label-media", (tr!("Drive"), tr!("Label Media")));
+ register_task_description("load-media", |_ty, id: Option<String>| {
+ render_drive_load_media_id(&id.unwrap_or_default(), &tr!("Load Media"))
+ });
+ register_task_description("logrotate", tr!("Log Rotation"));
+ register_task_description("mount-device", (tr!("Datastore"), tr!("Mount Device")));
+ register_task_description(
+ "mount-sync-jobs",
+ (
+ tr!("Datastore"),
+ tr!("sync jobs handler triggered by mount"),
+ ),
+ );
+ register_task_description("prune", |_ty, id: Option<String>| {
+ render_datastore_worker_id(id, &tr!("Prune"))
+ });
+ register_task_description("prunejob", |_ty, id: Option<String>| {
+ render_prune_job_worker_id(id, &tr!("Prune Job"))
+ });
+ register_task_description("reader", |_ty, id: Option<String>| {
+ render_datastore_worker_id(id, &tr!("Read Objects"))
+ });
+ register_task_description("rewind-media", (tr!("Drive"), tr!("Rewind Media")));
+ register_task_description("s3-refresh", (tr!("Datastore"), tr!("S3 Refresh")));
+ register_task_description("sync", (tr!("Datastore"), tr!("Remote Sync")));
+ register_task_description("syncjob", (tr!("Sync Job"), tr!("Remote Sync")));
+ register_task_description("tape-backup", |_ty, id: Option<String>| {
+ render_tape_backup_id(id, &tr!("Tape Backup"))
+ });
+ register_task_description("tape-backup-job", |_ty, id: Option<String>| {
+ render_tape_backup_id(id, &tr!("Tape Backup Job"))
+ });
+ register_task_description("tape-restore", (tr!("Datastore"), tr!("Tape Restore")));
+ register_task_description("unload-media", (tr!("Drive"), tr!("Unload Media")));
+ register_task_description("unmount-device", (tr!("Datastore"), tr!("Unmount Device")));
+ register_task_description(
+ "verificationjob",
+ (tr!("Verify Job"), tr!("Scheduled Verification")),
+ );
+ register_task_description("verify", (tr!("Datastore"), tr!("Verification")));
+ register_task_description("verify_group", (tr!("Group"), tr!("Verification")));
+ register_task_description("verify_snapshot", (tr!("Snapshot"), tr!("Verification")));
+ register_task_description("wipedisk", (tr!("Device"), tr!("Wipe Disk")));
+ register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
+}
+
+proxmox_schema::const_regex! {
+ DATASTORE_WORKER_ID_REGEX = r"^(\S+?):(\S+?)/(\S+?)(/(.+))?$";
+}
+
+fn render_datastore_worker_id(id: Option<String>, what: &str) -> String {
+ let id = id.as_deref().unwrap_or("unknown");
+
+ if let Some(cap) = DATASTORE_WORKER_ID_REGEX.captures(id) {
+ let datastore = cap.get(1).map(|m| m.as_str());
+ let res2 = cap.get(2).map(|m| m.as_str());
+ let res3 = cap.get(3).map(|m| m.as_str());
+ let epoch = cap.get(5).map(|m| m.as_str());
+
+ if let (Some(datastore), Some(res2), Some(res3), Some(epoch)) =
+ (datastore, res2, res3, epoch)
+ {
+ if let Ok(epoch) = i64::from_str_radix(epoch, 16) {
+ let utctime = proxmox_time::epoch_to_rfc3339_utc(epoch).unwrap_or_default();
+ return format!(
+ "{} {} {} {}/{} {}",
+ tr!("Datastore"),
+ datastore,
+ what,
+ res2,
+ res3,
+ utctime
+ );
+ }
+ }
+ }
+
+ format!("{} {} {}", tr!("Datastore"), id, what)
+}
+
+proxmox_schema::const_regex! {
+ PRUNE_JOB_WORKER_ID_REGEX = r"^(\S+?):(\S+)$";
+}
+
+fn render_prune_job_worker_id(id: Option<String>, what: &str) -> String {
+ let id = id.as_deref().unwrap_or("unknown");
+
+ if let Some(cap) = PRUNE_JOB_WORKER_ID_REGEX.captures(id) {
+ let datastore = cap.get(1).map(|m| m.as_str());
+ let namespace = cap.get(2).map(|m| m.as_str());
+
+ if let (Some(datastore), Some(namespace)) = (datastore, namespace) {
+ return format!(
+ "{} on {} {} {} {}",
+ what,
+ tr! {"Datastore"},
+ datastore,
+ tr!("Namespace"),
+ namespace
+ );
+ }
+ }
+ return format!("{} on {} {}", what, tr! {"Datastore"}, id);
+}
+
+proxmox_schema::const_regex! {
+ TAPE_WORKER_ID_REGEX = r"^(\S+?):(\S+?):(\S+?)(:(.+))?$";
+}
+
+fn render_tape_backup_id(id: Option<String>, what: &str) -> String {
+ let id = id.as_deref().unwrap_or("unknown");
+
+ if let Some(cap) = TAPE_WORKER_ID_REGEX.captures(id) {
+ let datastore = cap.get(1).map(|m| m.as_str());
+ let pool = cap.get(2).map(|m| m.as_str());
+ let drive = cap.get(3).map(|m| m.as_str());
+
+ if let (Some(datastore), Some(pool), Some(drive)) = (datastore, pool, drive) {
+ return format!("{} {} (pool {}, drive {})", what, datastore, pool, drive);
+ }
+ }
+ format!("{} {}", what, id)
+}
+
+proxmox_schema::const_regex! {
+ DRIVE_LOAD_WORKER_ID_REGEX = r"^(\S+?):(\S+?)$";
+}
+
+fn render_drive_load_media_id(id: &str, what: &str) -> String {
+ if let Some(caps) = DRIVE_LOAD_WORKER_ID_REGEX.captures(id) {
+ let drive = &caps[1];
+ let label = &caps[2];
+ return format!("{} {drive} - {what} '{label}'", tr!("Drive"));
+ }
+
+ format!("{what} {id}")
+}
--
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] 11+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 1/2] ui: register task descriptions for some native PDM tasks
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions Lukas Wagner
@ 2025-12-18 9:51 ` Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 2/2] ui: use task descriptions from yew-comp for PBS and PVE Lukas Wagner
2025-12-18 12:19 ` [pdm-devel] superseded: [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
4 siblings, 0 replies; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 9:51 UTC (permalink / raw)
To: pdm-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
ui/src/lib.rs | 2 +-
ui/src/main.rs | 7 ++++---
ui/src/tasks.rs | 19 ++++++++++++++++++-
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/ui/src/lib.rs b/ui/src/lib.rs
index 1aac7571..674cb27b 100644
--- a/ui/src/lib.rs
+++ b/ui/src/lib.rs
@@ -54,7 +54,7 @@ mod load_result;
pub use load_result::LoadResult;
mod tasks;
-pub use tasks::register_pve_tasks;
+pub use tasks::register_tasks;
mod view_list_context;
pub use view_list_context::ViewListContext;
diff --git a/ui/src/main.rs b/ui/src/main.rs
index 5f859dbc..56ae7429 100644
--- a/ui/src/main.rs
+++ b/ui/src/main.rs
@@ -23,8 +23,8 @@ use proxmox_yew_comp::{
//use pbs::MainMenu;
use pdm_api_types::views::ViewConfig;
use pdm_ui::{
- check_pdm_subscription, pdm_subscription_alert, register_pve_tasks, MainMenu, RemoteList,
- RemoteListCacheEntry, SearchProvider, TopNavBar, ViewListContext,
+ check_pdm_subscription, pdm_subscription_alert, MainMenu, RemoteList, RemoteListCacheEntry,
+ SearchProvider, TopNavBar, ViewListContext,
};
type MsgRemoteList = Result<RemoteList, Error>;
@@ -380,7 +380,8 @@ fn main() {
yew::set_custom_panic_hook(panic_hook());
init_task_descr_table_base();
- register_pve_tasks();
+ pdm_ui::register_tasks();
+
proxmox_yew_comp::http_setup(&proxmox_yew_comp::ExistingProduct::PDM);
pwt::props::set_http_get_method(
diff --git a/ui/src/tasks.rs b/ui/src/tasks.rs
index 0f9a9aa7..7e40863d 100644
--- a/ui/src/tasks.rs
+++ b/ui/src/tasks.rs
@@ -4,7 +4,12 @@ use pwt::tr;
use pdm_api_types::{NativeUpid, RemoteUpid};
use yew::virtual_dom::Key;
-pub fn register_pve_tasks() {
+pub fn register_tasks() {
+ register_pve_tasks();
+ register_pdm_tasks();
+}
+
+fn register_pve_tasks() {
register_task_description("qmstart", ("VM", tr!("Start")));
register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
@@ -107,6 +112,18 @@ pub fn register_pve_tasks() {
register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
}
+fn register_pdm_tasks() {
+ register_task_description("logrotate", tr!("Log Rotation"));
+ register_task_description(
+ "refresh-remote-tasks",
+ tr!("Fetch latest tasks from remotes"),
+ );
+ register_task_description(
+ "refresh-remote-updates",
+ tr!("Fetch system update list from remotes"),
+ );
+}
+
/// Format a UPID that is either [`RemoteUpid`] or a [`UPID`]
/// If it's a [`RemoteUpid`], prefixes it with the remote name
pub fn format_optional_remote_upid(upid: &str, include_remote: bool) -> String {
--
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] 11+ messages in thread
* [pdm-devel] [PATCH datacenter-manager 2/2] ui: use task descriptions from yew-comp for PBS and PVE
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
` (2 preceding siblings ...)
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 1/2] ui: register task descriptions for some native PDM tasks Lukas Wagner
@ 2025-12-18 9:51 ` Lukas Wagner
2025-12-18 12:19 ` [pdm-devel] superseded: [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
4 siblings, 0 replies; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 9:51 UTC (permalink / raw)
To: pdm-devel
Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
ui/src/tasks.rs | 109 +++---------------------------------------------
1 file changed, 5 insertions(+), 104 deletions(-)
diff --git a/ui/src/tasks.rs b/ui/src/tasks.rs
index 7e40863d..f0931c9e 100644
--- a/ui/src/tasks.rs
+++ b/ui/src/tasks.rs
@@ -1,4 +1,7 @@
-use proxmox_yew_comp::utils::{format_task_description, format_upid, register_task_description};
+use proxmox_yew_comp::utils::{
+ format_task_description, format_upid, register_pbs_tasks, register_pve_tasks,
+ register_task_description,
+};
use pwt::tr;
use pdm_api_types::{NativeUpid, RemoteUpid};
@@ -6,112 +9,10 @@ use yew::virtual_dom::Key;
pub fn register_tasks() {
register_pve_tasks();
+ register_pbs_tasks();
register_pdm_tasks();
}
-fn register_pve_tasks() {
- register_task_description("qmstart", ("VM", tr!("Start")));
- register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
- register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
- register_task_description("acmerefresh", ("ACME Account", tr!("Refresh")));
- register_task_description("acmeregister", ("ACME Account", tr!("Register")));
- register_task_description("acmerenew", ("SRV", tr!("Renew Certificate")));
- register_task_description("acmerevoke", ("SRV", tr!("Revoke Certificate")));
- register_task_description("acmeupdate", ("ACME Account", tr!("Update")));
- register_task_description("auth-realm-sync", (tr!("Realm"), tr!("Sync")));
- register_task_description("auth-realm-sync-test", (tr!("Realm"), tr!("Sync Preview")));
- register_task_description("cephcreatemds", ("Ceph Metadata Server", tr!("Create")));
- register_task_description("cephcreatemgr", ("Ceph Manager", tr!("Create")));
- register_task_description("cephcreatemon", ("Ceph Monitor", tr!("Create")));
- register_task_description("cephcreateosd", ("Ceph OSD", tr!("Create")));
- register_task_description("cephcreatepool", ("Ceph Pool", tr!("Create")));
- register_task_description("cephdestroymds", ("Ceph Metadata Server", tr!("Destroy")));
- register_task_description("cephdestroymgr", ("Ceph Manager", tr!("Destroy")));
- register_task_description("cephdestroymon", ("Ceph Monitor", tr!("Destroy")));
- register_task_description("cephdestroyosd", ("Ceph OSD", tr!("Destroy")));
- register_task_description("cephdestroypool", ("Ceph Pool", tr!("Destroy")));
- register_task_description("cephdestroyfs", ("CephFS", tr!("Destroy")));
- register_task_description("cephfscreate", ("CephFS", tr!("Create")));
- register_task_description("cephsetpool", ("Ceph Pool", tr!("Edit")));
- register_task_description("cephsetflags", tr!("Change global Ceph flags"));
- register_task_description("clustercreate", tr!("Create Cluster"));
- register_task_description("clusterjoin", tr!("Join Cluster"));
- register_task_description("create_zone", tr!("Create EVPN Zone"));
- register_task_description("create_vnet", tr!("Create EVPN VNet"));
- register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
- register_task_description("dirremove", (tr!("Directory"), tr!("Remove")));
- register_task_description("download", (tr!("File"), tr!("Download")));
- register_task_description("hamigrate", ("HA", tr!("Migrate")));
- register_task_description("hashutdown", ("HA", tr!("Shutdown")));
- register_task_description("hastart", ("HA", tr!("Start")));
- register_task_description("hastop", ("HA", tr!("Stop")));
- register_task_description("imgcopy", tr!("Copy data"));
- register_task_description("imgdel", tr!("Erase data"));
- register_task_description("lvmcreate", (tr!("LVM Storage"), tr!("Create")));
- register_task_description("lvmremove", ("Volume Group", tr!("Remove")));
- register_task_description("lvmthincreate", (tr!("LVM-Thin Storage"), tr!("Create")));
- register_task_description("lvmthinremove", ("Thinpool", tr!("Remove")));
- register_task_description("migrateall", tr!("Bulk migrate VMs and Containers"));
- register_task_description("move_volume", ("CT", tr!("Move Volume")));
- register_task_description("pbs-download", ("VM/CT", tr!("File Restore Download")));
- register_task_description("pull_file", ("CT", tr!("Pull file")));
- register_task_description("push_file", ("CT", tr!("Push file")));
- register_task_description("qmclone", ("VM", tr!("Clone")));
- register_task_description("qmconfig", ("VM", tr!("Configure")));
- register_task_description("qmcreate", ("VM", tr!("Create")));
- register_task_description("qmdelsnapshot", ("VM", tr!("Delete Snapshot")));
- register_task_description("qmdestroy", ("VM", tr!("Destroy")));
- register_task_description("qmigrate", ("VM", tr!("Migrate")));
- register_task_description("qmmove", ("VM", tr!("Move disk")));
- register_task_description("qmpause", ("VM", tr!("Pause")));
- register_task_description("qmreboot", ("VM", tr!("Reboot")));
- register_task_description("qmreset", ("VM", tr!("Reset")));
- register_task_description("qmrestore", ("VM", tr!("Restore")));
- register_task_description("qmresume", ("VM", tr!("Resume")));
- register_task_description("qmrollback", ("VM", tr!("Rollback")));
- register_task_description("qmshutdown", ("VM", tr!("Shutdown")));
- register_task_description("qmsnapshot", ("VM", tr!("Snapshot")));
- register_task_description("qmstart", ("VM", tr!("Start")));
- register_task_description("qmstop", ("VM", tr!("Stop")));
- register_task_description("qmsuspend", ("VM", tr!("Hibernate")));
- register_task_description("qmtemplate", ("VM", tr!("Convert to template")));
- register_task_description("reloadnetworkall", tr!("Apply SDN configuration"));
- register_task_description("resize", ("VM/CT", tr!("Resize")));
- register_task_description("spiceproxy", ("VM/CT", tr!("Console") + " (Spice)"));
- register_task_description("spiceshell", tr!("Shell") + " (Spice)");
- register_task_description("srvreload", tr!("Reload network configuration"));
- register_task_description("startall", tr!("Bulk start VMs and Containers"));
- register_task_description("stopall", tr!("Bulk shutdown VMs and Containers"));
- register_task_description("suspendall", tr!("Suspend all VMs"));
- register_task_description("unknownimgdel", tr!("Destroy image from unknown guest"));
- register_task_description("wipedisk", ("Device", tr!("Wipe Disk")));
- register_task_description("vncproxy", ("VM/CT", tr!("Console")));
- register_task_description("vncshell", tr!("Shell"));
- register_task_description("vzclone", ("CT", tr!("Clone")));
- register_task_description("vzcreate", ("CT", tr!("Create")));
- register_task_description("vzdelsnapshot", ("CT", tr!("Delete Snapshot")));
- register_task_description("vzdestroy", ("CT", tr!("Destroy")));
- register_task_description("vzdump", |_ty, id| match id {
- Some(id) => format!("VM/CT {id} - {}", tr!("Backup")),
- None => tr!("Backup Job"),
- });
- register_task_description("vzmigrate", ("CT", tr!("Migrate")));
- register_task_description("vzmount", ("CT", tr!("Mount")));
- register_task_description("vzreboot", ("CT", tr!("Reboot")));
- register_task_description("vzrestore", ("CT", tr!("Restore")));
- register_task_description("vzresume", ("CT", tr!("Resume")));
- register_task_description("vzrollback", ("CT", tr!("Rollback")));
- register_task_description("vzshutdown", ("CT", tr!("Shutdown")));
- register_task_description("vzsnapshot", ("CT", tr!("Snapshot")));
- register_task_description("vzstart", ("CT", tr!("Start")));
- register_task_description("vzstop", ("CT", tr!("Stop")));
- register_task_description("vzsuspend", ("CT", tr!("Suspend")));
- register_task_description("vztemplate", ("CT", tr!("Convert to template")));
- register_task_description("vzumount", ("CT", tr!("Unmount")));
- register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
- register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
-}
-
fn register_pdm_tasks() {
register_task_description("logrotate", tr!("Log Rotation"));
register_task_description(
--
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] 11+ messages in thread
* Re: [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule Lukas Wagner
@ 2025-12-18 11:49 ` Dominik Csapak
2025-12-18 12:05 ` Lukas Wagner
0 siblings, 1 reply; 11+ messages in thread
From: Dominik Csapak @ 2025-12-18 11:49 UTC (permalink / raw)
To: Proxmox Datacenter Manager development discussion, Lukas Wagner
Looks mostly good, but it seems there were some task descriptions
that were added. It's not a big deal, but I'd prefer it to
have the new ones added as their own commit or at least
mentioned in the commit message.
i saw the following new ones:
create_vnet
create_zone
reloadnetworkall
was that intended?
On 12/18/25 10:52 AM, Lukas Wagner wrote:
> No functional changes. Reexports from the 'utils' module ensure that
> clients don't have to change.
>
> Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
> ---
> src/utils/mod.rs | 228 ++-------------------------------
> src/utils/task_descriptions.rs | 214 +++++++++++++++++++++++++++++++
> 2 files changed, 226 insertions(+), 216 deletions(-)
> create mode 100644 src/utils/task_descriptions.rs
>
> diff --git a/src/utils/mod.rs b/src/utils/mod.rs
> index 856297f..600e436 100644
> --- a/src/utils/mod.rs
> +++ b/src/utils/mod.rs
> @@ -1,6 +1,4 @@
> use std::collections::HashMap;
> -use std::fmt::Display;
> -use std::sync::Mutex;
>
> use percent_encoding::percent_decode;
> use serde_json::Value;
> @@ -11,9 +9,13 @@ use crate::common_api_types::ProxmoxUpid;
> use pwt::tr;
>
> mod clipboard;
> +mod task_descriptions;
> +
> #[allow(deprecated)]
> pub use clipboard::{copy_text_to_clipboard, copy_to_clipboard};
>
> +pub use task_descriptions::*;
> +
> /// Somewhat like a human would tell durations, omit zero values and do not
> /// give seconds precision if we talk days already
> pub fn format_duration_human(ut: f64) -> String {
> @@ -154,122 +156,6 @@ pub fn epoch_to_input_value(epoch: i64) -> String {
> }
> }
>
> -// todo: we want to use Fn(&str, Option<&str>),
> -#[allow(clippy::type_complexity)]
> -static TASK_DESCR_TABLE: Mutex<
> - Option<HashMap<String, Box<dyn Send + Sync + Fn(String, Option<String>) -> String>>>,
> -> = Mutex::new(None);
> -
> -pub trait IntoTaskDescriptionRenderFn {
> - fn into_task_description_render_fn(
> - self,
> - ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String>;
> -}
> -
> -impl<F: 'static + Send + Sync + Fn(String, Option<String>) -> String> IntoTaskDescriptionRenderFn
> - for F
> -{
> - fn into_task_description_render_fn(
> - self,
> - ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String> {
> - Box::new(self)
> - }
> -}
> -
> -impl<A: Display, B: Display> IntoTaskDescriptionRenderFn for (A, B) {
> - fn into_task_description_render_fn(
> - self,
> - ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
> - let task_type = self.0.to_string();
> - let action = self.1.to_string();
> - Box::new(move |_, id| {
> - format!(
> - "{} {} {}",
> - task_type,
> - id.as_deref().unwrap_or("unknown"),
> - action
> - )
> - })
> - }
> -}
> -
> -impl IntoTaskDescriptionRenderFn for String {
> - fn into_task_description_render_fn(
> - self,
> - ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
> - Box::new(move |_, _id| self.clone())
> - }
> -}
> -
> -pub fn register_task_description(
> - name: impl Into<String>,
> - render: impl IntoTaskDescriptionRenderFn,
> -) {
> - let mut map = TASK_DESCR_TABLE.lock().unwrap();
> - if map.is_none() {
> - *map = Some(HashMap::new());
> - }
> -
> - let map = map.as_mut().unwrap();
> -
> - let name: String = name.into();
> - let render = render.into_task_description_render_fn();
> -
> - map.insert(name, render);
> -}
> -
> -pub fn lookup_task_description(name: &str, id: Option<&str>) -> Option<String> {
> - let map = TASK_DESCR_TABLE.lock().unwrap();
> - match *map {
> - Some(ref map) => map
> - .get(name)
> - .map(|function| function(name.to_string(), id.map(|id| id.to_string()))),
> - None => None,
> - }
> -}
> -
> -pub fn registered_task_types() -> Vec<String> {
> - let map = TASK_DESCR_TABLE.lock().unwrap();
> - match *map {
> - Some(ref map) => map.keys().map(|t| t.to_string()).collect(),
> - None => Vec::new(),
> - }
> -}
> -
> -pub fn init_task_descr_table_base() {
> - register_task_description("aptupdate", tr!("Update package database"));
> - // TRANSLATORS: Spice is a proper name, see https://www.spice-space.org
> - register_task_description("spiceshell", tr!("Shell (Spice)"));
> - register_task_description("vncshell", tr!("Shell (VNC)"));
> - register_task_description("termproxy", tr!("Console (xterm.js)"));
> -
> - register_task_description("diskinit", (tr!("Disk"), tr!("Initialize Disk with GPT")));
> - register_task_description("srvstart", (tr!("Service"), tr!("Start")));
> - register_task_description("srvstop", (tr!("Service"), tr!("Stop")));
> - register_task_description("srvrestart", (tr!("Service"), tr!("Restart")));
> - register_task_description("srvreload", (tr!("Service"), tr!("Reload")));
> -}
> -
> -/// Uses information from the given `UPID` to render the task description with [`format_task_description`]
> -pub fn format_upid(upid: &str) -> String {
> - match upid.parse::<ProxmoxUpid>() {
> - Err(_) => upid.to_string(),
> - Ok(upid) => format_task_description(&upid.worker_type, upid.worker_id.as_deref()),
> - }
> -}
> -
> -/// Formats the given worker type and id to a Human readable task description
> -pub fn format_task_description(worker_type: &str, worker_id: Option<&str>) -> String {
> - if let Some(text) = lookup_task_description(worker_type, worker_id) {
> - text
> - } else {
> - match worker_id {
> - Some(id) => format!("{} {}", worker_type, id),
> - None => worker_type.to_string(),
> - }
> - }
> -}
> -
> pub struct AuthDomainInfo {
> pub ty: String, // type
> //pub description: String,
> @@ -349,104 +235,14 @@ pub fn set_location_href(href: &str) {
> let _ = location.set_href(href);
> }
>
> -/// Register PVE task descriptions
> -pub fn register_pve_tasks() {
> - register_task_description("qmstart", ("VM", tr!("Start")));
> - register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
> - register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
> - register_task_description("acmerefresh", ("ACME Account", tr!("Refresh")));
> - register_task_description("acmeregister", ("ACME Account", tr!("Register")));
> - register_task_description("acmerenew", ("SRV", tr!("Renew Certificate")));
> - register_task_description("acmerevoke", ("SRV", tr!("Revoke Certificate")));
> - register_task_description("acmeupdate", ("ACME Account", tr!("Update")));
> - register_task_description("auth-realm-sync", (tr!("Realm"), tr!("Sync")));
> - register_task_description("auth-realm-sync-test", (tr!("Realm"), tr!("Sync Preview")));
> - register_task_description("cephcreatemds", ("Ceph Metadata Server", tr!("Create")));
> - register_task_description("cephcreatemgr", ("Ceph Manager", tr!("Create")));
> - register_task_description("cephcreatemon", ("Ceph Monitor", tr!("Create")));
> - register_task_description("cephcreateosd", ("Ceph OSD", tr!("Create")));
> - register_task_description("cephcreatepool", ("Ceph Pool", tr!("Create")));
> - register_task_description("cephdestroymds", ("Ceph Metadata Server", tr!("Destroy")));
> - register_task_description("cephdestroymgr", ("Ceph Manager", tr!("Destroy")));
> - register_task_description("cephdestroymon", ("Ceph Monitor", tr!("Destroy")));
> - register_task_description("cephdestroyosd", ("Ceph OSD", tr!("Destroy")));
> - register_task_description("cephdestroypool", ("Ceph Pool", tr!("Destroy")));
> - register_task_description("cephdestroyfs", ("CephFS", tr!("Destroy")));
> - register_task_description("cephfscreate", ("CephFS", tr!("Create")));
> - register_task_description("cephsetpool", ("Ceph Pool", tr!("Edit")));
> - register_task_description("cephsetflags", tr!("Change global Ceph flags"));
> - register_task_description("clustercreate", tr!("Create Cluster"));
> - register_task_description("clusterjoin", tr!("Join Cluster"));
> - register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
> - register_task_description("dirremove", (tr!("Directory"), tr!("Remove")));
> - register_task_description("download", (tr!("File"), tr!("Download")));
> - register_task_description("hamigrate", ("HA", tr!("Migrate")));
> - register_task_description("hashutdown", ("HA", tr!("Shutdown")));
> - register_task_description("hastart", ("HA", tr!("Start")));
> - register_task_description("hastop", ("HA", tr!("Stop")));
> - register_task_description("imgcopy", tr!("Copy data"));
> - register_task_description("imgdel", tr!("Erase data"));
> - register_task_description("lvmcreate", (tr!("LVM Storage"), tr!("Create")));
> - register_task_description("lvmremove", ("Volume Group", tr!("Remove")));
> - register_task_description("lvmthincreate", (tr!("LVM-Thin Storage"), tr!("Create")));
> - register_task_description("lvmthinremove", ("Thinpool", tr!("Remove")));
> - register_task_description("migrateall", tr!("Bulk migrate VMs and Containers"));
> - register_task_description("move_volume", ("CT", tr!("Move Volume")));
> - register_task_description("pbs-download", ("VM/CT", tr!("File Restore Download")));
> - register_task_description("pull_file", ("CT", tr!("Pull file")));
> - register_task_description("push_file", ("CT", tr!("Push file")));
> - register_task_description("qmclone", ("VM", tr!("Clone")));
> - register_task_description("qmconfig", ("VM", tr!("Configure")));
> - register_task_description("qmcreate", ("VM", tr!("Create")));
> - register_task_description("qmdelsnapshot", ("VM", tr!("Delete Snapshot")));
> - register_task_description("qmdestroy", ("VM", tr!("Destroy")));
> - register_task_description("qmigrate", ("VM", tr!("Migrate")));
> - register_task_description("qmmove", ("VM", tr!("Move disk")));
> - register_task_description("qmpause", ("VM", tr!("Pause")));
> - register_task_description("qmreboot", ("VM", tr!("Reboot")));
> - register_task_description("qmreset", ("VM", tr!("Reset")));
> - register_task_description("qmrestore", ("VM", tr!("Restore")));
> - register_task_description("qmresume", ("VM", tr!("Resume")));
> - register_task_description("qmrollback", ("VM", tr!("Rollback")));
> - register_task_description("qmshutdown", ("VM", tr!("Shutdown")));
> - register_task_description("qmsnapshot", ("VM", tr!("Snapshot")));
> - register_task_description("qmstart", ("VM", tr!("Start")));
> - register_task_description("qmstop", ("VM", tr!("Stop")));
> - register_task_description("qmsuspend", ("VM", tr!("Hibernate")));
> - register_task_description("qmtemplate", ("VM", tr!("Convert to template")));
> - register_task_description("resize", ("VM/CT", tr!("Resize")));
> - register_task_description("spiceproxy", ("VM/CT", tr!("Console") + " (Spice)"));
> - register_task_description("spiceshell", tr!("Shell") + " (Spice)");
> - register_task_description("startall", tr!("Bulk start VMs and Containers"));
> - register_task_description("stopall", tr!("Bulk shutdown VMs and Containers"));
> - register_task_description("suspendall", tr!("Suspend all VMs"));
> - register_task_description("unknownimgdel", tr!("Destroy image from unknown guest"));
> - register_task_description("wipedisk", ("Device", tr!("Wipe Disk")));
> - register_task_description("vncproxy", ("VM/CT", tr!("Console")));
> - register_task_description("vncshell", tr!("Shell"));
> - register_task_description("vzclone", ("CT", tr!("Clone")));
> - register_task_description("vzcreate", ("CT", tr!("Create")));
> - register_task_description("vzdelsnapshot", ("CT", tr!("Delete Snapshot")));
> - register_task_description("vzdestroy", ("CT", tr!("Destroy")));
> - register_task_description("vzdump", |_ty, id| match id {
> - Some(id) => format!("VM/CT {id} - {}", tr!("Backup")),
> - None => tr!("Backup Job"),
> - });
> - register_task_description("vzmigrate", ("CT", tr!("Migrate")));
> - register_task_description("vzmount", ("CT", tr!("Mount")));
> - register_task_description("vzreboot", ("CT", tr!("Reboot")));
> - register_task_description("vzrestore", ("CT", tr!("Restore")));
> - register_task_description("vzresume", ("CT", tr!("Resume")));
> - register_task_description("vzrollback", ("CT", tr!("Rollback")));
> - register_task_description("vzshutdown", ("CT", tr!("Shutdown")));
> - register_task_description("vzsnapshot", ("CT", tr!("Snapshot")));
> - register_task_description("vzstart", ("CT", tr!("Start")));
> - register_task_description("vzstop", ("CT", tr!("Stop")));
> - register_task_description("vzsuspend", ("CT", tr!("Suspend")));
> - register_task_description("vztemplate", ("CT", tr!("Convert to template")));
> - register_task_description("vzumount", ("CT", tr!("Unmount")));
> - register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
> - register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
> +/// Uses information from the given `UPID` to render the task description with [`format_task_description`]
> +pub fn format_upid(upid: &str) -> String {
> + match upid.parse::<ProxmoxUpid>() {
> + Err(_) => upid.to_string(),
> + Ok(upid) => {
> + task_descriptions::format_task_description(&upid.worker_type, upid.worker_id.as_deref())
> + }
> + }
> }
>
> pub fn openid_redirection_authorization() -> Option<HashMap<String, String>> {
> diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
> new file mode 100644
> index 0000000..86525a4
> --- /dev/null
> +++ b/src/utils/task_descriptions.rs
> @@ -0,0 +1,214 @@
> +use std::{collections::HashMap, fmt::Display, sync::Mutex};
> +
> +use pwt::tr;
> +
> +// todo: we want to use Fn(&str, Option<&str>),
> +#[allow(clippy::type_complexity)]
> +static TASK_DESCR_TABLE: Mutex<
> + Option<HashMap<String, Box<dyn Send + Sync + Fn(String, Option<String>) -> String>>>,
> +> = Mutex::new(None);
> +
> +pub trait IntoTaskDescriptionRenderFn {
> + fn into_task_description_render_fn(
> + self,
> + ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String>;
> +}
> +
> +impl<F: 'static + Send + Sync + Fn(String, Option<String>) -> String> IntoTaskDescriptionRenderFn
> + for F
> +{
> + fn into_task_description_render_fn(
> + self,
> + ) -> Box<dyn Send + Sync + Fn(String, Option<String>) -> String> {
> + Box::new(self)
> + }
> +}
> +
> +impl<A: Display, B: Display> IntoTaskDescriptionRenderFn for (A, B) {
> + fn into_task_description_render_fn(
> + self,
> + ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
> + let task_type = self.0.to_string();
> + let action = self.1.to_string();
> + Box::new(move |_, id| {
> + format!(
> + "{} {} {}",
> + task_type,
> + id.as_deref().unwrap_or("unknown"),
> + action
> + )
> + })
> + }
> +}
> +
> +impl IntoTaskDescriptionRenderFn for String {
> + fn into_task_description_render_fn(
> + self,
> + ) -> Box<dyn 'static + Send + Sync + Fn(String, Option<String>) -> String> {
> + Box::new(move |_, _id| self.clone())
> + }
> +}
> +
> +pub fn register_task_description(
> + name: impl Into<String>,
> + render: impl IntoTaskDescriptionRenderFn,
> +) {
> + let mut map = TASK_DESCR_TABLE.lock().unwrap();
> + if map.is_none() {
> + *map = Some(HashMap::new());
> + }
> +
> + let map = map.as_mut().unwrap();
> +
> + let name: String = name.into();
> + let render = render.into_task_description_render_fn();
> +
> + map.insert(name, render);
> +}
> +
> +pub fn lookup_task_description(name: &str, id: Option<&str>) -> Option<String> {
> + let map = TASK_DESCR_TABLE.lock().unwrap();
> + match *map {
> + Some(ref map) => map
> + .get(name)
> + .map(|function| function(name.to_string(), id.map(|id| id.to_string()))),
> + None => None,
> + }
> +}
> +
> +pub fn registered_task_types() -> Vec<String> {
> + let map = TASK_DESCR_TABLE.lock().unwrap();
> + match *map {
> + Some(ref map) => map.keys().map(|t| t.to_string()).collect(),
> + None => Vec::new(),
> + }
> +}
> +
> +pub fn init_task_descr_table_base() {
> + register_task_description("aptupdate", tr!("Update package database"));
> + // TRANSLATORS: Spice is a proper name, see https://www.spice-space.org
> + register_task_description("spiceshell", tr!("Shell (Spice)"));
> + register_task_description("vncshell", tr!("Shell (VNC)"));
> + register_task_description("termproxy", tr!("Console (xterm.js)"));
> +
> + register_task_description("diskinit", (tr!("Disk"), tr!("Initialize Disk with GPT")));
> + register_task_description("srvstart", (tr!("Service"), tr!("Start")));
> + register_task_description("srvstop", (tr!("Service"), tr!("Stop")));
> + register_task_description("srvrestart", (tr!("Service"), tr!("Restart")));
> + register_task_description("srvreload", (tr!("Service"), tr!("Reload")));
> +}
> +
> +/// Formats the given worker type and id to a Human readable task description
> +pub fn format_task_description(worker_type: &str, worker_id: Option<&str>) -> String {
> + if let Some(text) = lookup_task_description(worker_type, worker_id) {
> + text
> + } else {
> + match worker_id {
> + Some(id) => format!("{} {}", worker_type, id),
> + None => worker_type.to_string(),
> + }
> + }
> +}
> +
> +/// Register PVE task descriptions
> +pub fn register_pve_tasks() {
> + register_task_description("qmstart", ("VM", tr!("Start")));
> + register_task_description("acmedeactivate", ("ACME Account", tr!("Deactivate")));
> + register_task_description("acmenewcert", ("SRV", tr!("Order Certificate")));
> + register_task_description("acmerefresh", ("ACME Account", tr!("Refresh")));
> + register_task_description("acmeregister", ("ACME Account", tr!("Register")));
> + register_task_description("acmerenew", ("SRV", tr!("Renew Certificate")));
> + register_task_description("acmerevoke", ("SRV", tr!("Revoke Certificate")));
> + register_task_description("acmeupdate", ("ACME Account", tr!("Update")));
> + register_task_description("auth-realm-sync", (tr!("Realm"), tr!("Sync")));
> + register_task_description("auth-realm-sync-test", (tr!("Realm"), tr!("Sync Preview")));
> + register_task_description("cephcreatemds", ("Ceph Metadata Server", tr!("Create")));
> + register_task_description("cephcreatemgr", ("Ceph Manager", tr!("Create")));
> + register_task_description("cephcreatemon", ("Ceph Monitor", tr!("Create")));
> + register_task_description("cephcreateosd", ("Ceph OSD", tr!("Create")));
> + register_task_description("cephcreatepool", ("Ceph Pool", tr!("Create")));
> + register_task_description("cephdestroymds", ("Ceph Metadata Server", tr!("Destroy")));
> + register_task_description("cephdestroymgr", ("Ceph Manager", tr!("Destroy")));
> + register_task_description("cephdestroymon", ("Ceph Monitor", tr!("Destroy")));
> + register_task_description("cephdestroyosd", ("Ceph OSD", tr!("Destroy")));
> + register_task_description("cephdestroypool", ("Ceph Pool", tr!("Destroy")));
> + register_task_description("cephdestroyfs", ("CephFS", tr!("Destroy")));
> + register_task_description("cephfscreate", ("CephFS", tr!("Create")));
> + register_task_description("cephsetpool", ("Ceph Pool", tr!("Edit")));
> + register_task_description("cephsetflags", tr!("Change global Ceph flags"));
> + register_task_description("clustercreate", tr!("Create Cluster"));
> + register_task_description("clusterjoin", tr!("Join Cluster"));
> + register_task_description("create_zone", tr!("Create EVPN Zone"));
> + register_task_description("create_vnet", tr!("Create EVPN VNet"));
> + register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
> + register_task_description("dirremove", (tr!("Directory"), tr!("Remove")));
> + register_task_description("download", (tr!("File"), tr!("Download")));
> + register_task_description("hamigrate", ("HA", tr!("Migrate")));
> + register_task_description("hashutdown", ("HA", tr!("Shutdown")));
> + register_task_description("hastart", ("HA", tr!("Start")));
> + register_task_description("hastop", ("HA", tr!("Stop")));
> + register_task_description("imgcopy", tr!("Copy data"));
> + register_task_description("imgdel", tr!("Erase data"));
> + register_task_description("lvmcreate", (tr!("LVM Storage"), tr!("Create")));
> + register_task_description("lvmremove", ("Volume Group", tr!("Remove")));
> + register_task_description("lvmthincreate", (tr!("LVM-Thin Storage"), tr!("Create")));
> + register_task_description("lvmthinremove", ("Thinpool", tr!("Remove")));
> + register_task_description("migrateall", tr!("Bulk migrate VMs and Containers"));
> + register_task_description("move_volume", ("CT", tr!("Move Volume")));
> + register_task_description("pbs-download", ("VM/CT", tr!("File Restore Download")));
> + register_task_description("pull_file", ("CT", tr!("Pull file")));
> + register_task_description("push_file", ("CT", tr!("Push file")));
> + register_task_description("qmclone", ("VM", tr!("Clone")));
> + register_task_description("qmconfig", ("VM", tr!("Configure")));
> + register_task_description("qmcreate", ("VM", tr!("Create")));
> + register_task_description("qmdelsnapshot", ("VM", tr!("Delete Snapshot")));
> + register_task_description("qmdestroy", ("VM", tr!("Destroy")));
> + register_task_description("qmigrate", ("VM", tr!("Migrate")));
> + register_task_description("qmmove", ("VM", tr!("Move disk")));
> + register_task_description("qmpause", ("VM", tr!("Pause")));
> + register_task_description("qmreboot", ("VM", tr!("Reboot")));
> + register_task_description("qmreset", ("VM", tr!("Reset")));
> + register_task_description("qmrestore", ("VM", tr!("Restore")));
> + register_task_description("qmresume", ("VM", tr!("Resume")));
> + register_task_description("qmrollback", ("VM", tr!("Rollback")));
> + register_task_description("qmshutdown", ("VM", tr!("Shutdown")));
> + register_task_description("qmsnapshot", ("VM", tr!("Snapshot")));
> + register_task_description("qmstart", ("VM", tr!("Start")));
> + register_task_description("qmstop", ("VM", tr!("Stop")));
> + register_task_description("qmsuspend", ("VM", tr!("Hibernate")));
> + register_task_description("qmtemplate", ("VM", tr!("Convert to template")));
> + register_task_description("reloadnetworkall", tr!("Apply SDN configuration"));
> + register_task_description("resize", ("VM/CT", tr!("Resize")));
> + register_task_description("spiceproxy", ("VM/CT", tr!("Console") + " (Spice)"));
> + register_task_description("spiceshell", tr!("Shell") + " (Spice)");
> + register_task_description("startall", tr!("Bulk start VMs and Containers"));
> + register_task_description("stopall", tr!("Bulk shutdown VMs and Containers"));
> + register_task_description("suspendall", tr!("Suspend all VMs"));
> + register_task_description("unknownimgdel", tr!("Destroy image from unknown guest"));
> + register_task_description("wipedisk", ("Device", tr!("Wipe Disk")));
> + register_task_description("vncproxy", ("VM/CT", tr!("Console")));
> + register_task_description("vncshell", tr!("Shell"));
> + register_task_description("vzclone", ("CT", tr!("Clone")));
> + register_task_description("vzcreate", ("CT", tr!("Create")));
> + register_task_description("vzdelsnapshot", ("CT", tr!("Delete Snapshot")));
> + register_task_description("vzdestroy", ("CT", tr!("Destroy")));
> + register_task_description("vzdump", |_ty, id| match id {
> + Some(id) => format!("VM/CT {id} - {}", tr!("Backup")),
> + None => tr!("Backup Job"),
> + });
> + register_task_description("vzmigrate", ("CT", tr!("Migrate")));
> + register_task_description("vzmount", ("CT", tr!("Mount")));
> + register_task_description("vzreboot", ("CT", tr!("Reboot")));
> + register_task_description("vzrestore", ("CT", tr!("Restore")));
> + register_task_description("vzresume", ("CT", tr!("Resume")));
> + register_task_description("vzrollback", ("CT", tr!("Rollback")));
> + register_task_description("vzshutdown", ("CT", tr!("Shutdown")));
> + register_task_description("vzsnapshot", ("CT", tr!("Snapshot")));
> + register_task_description("vzstart", ("CT", tr!("Start")));
> + register_task_description("vzstop", ("CT", tr!("Stop")));
> + register_task_description("vzsuspend", ("CT", tr!("Suspend")));
> + register_task_description("vztemplate", ("CT", tr!("Convert to template")));
> + register_task_description("vzumount", ("CT", tr!("Unmount")));
> + register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
> + register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
> +}
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule
2025-12-18 11:49 ` Dominik Csapak
@ 2025-12-18 12:05 ` Lukas Wagner
0 siblings, 0 replies; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 12:05 UTC (permalink / raw)
To: Dominik Csapak,
Proxmox Datacenter Manager development discussion, Lukas Wagner
On Thu Dec 18, 2025 at 12:49 PM CET, Dominik Csapak wrote:
> Looks mostly good, but it seems there were some task descriptions
> that were added. It's not a big deal, but I'd prefer it to
> have the new ones added as their own commit or at least
> mentioned in the commit message.
>
> i saw the following new ones:
>
> create_vnet
> create_zone
> reloadnetworkall
>
> was that intended?
>
Ah, good catch. Intended to break them out into a separate commit when I
prepared these patches yesterday, but then forgot to do so today ^^
I'll send a v2.
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions Lukas Wagner
@ 2025-12-18 12:19 ` Dominik Csapak
2025-12-18 13:02 ` Lukas Wagner
0 siblings, 1 reply; 11+ messages in thread
From: Dominik Csapak @ 2025-12-18 12:19 UTC (permalink / raw)
To: Proxmox Datacenter Manager development discussion, Lukas Wagner
Looks mostly good to me, some comments inline
On 12/18/25 10:51 AM, Lukas Wagner wrote:
> Tried to make these match the JS ones as closely as possible. Some of
> these could be improved in the future, but this should then be done in
> tandem with the JS definitions.
>
> Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
> ---
> src/utils/task_descriptions.rs | 186 +++++++++++++++++++++++++++++++++
> 1 file changed, 186 insertions(+)
>
> diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
> index 86525a4..caeb563 100644
> --- a/src/utils/task_descriptions.rs
> +++ b/src/utils/task_descriptions.rs
> @@ -212,3 +212,189 @@ pub fn register_pve_tasks() {
> register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
> register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
> }
> +
> +/// Register PBS task descriptions.
> +pub fn register_pbs_tasks() {
> + register_task_description("acme-deativate", |_ty, id: Option<String>| {
> + let id = id.unwrap_or_else(|| "default".to_string());
> + tr!("Deactivate ACME Account - {0}", id)
> + });
> + register_task_description("acme-register", |_ty, id: Option<String>| {
> + let id = id.unwrap_or_else(|| "default".to_string());
> + tr!("Register ACME Account - {0}", id)
> + });
> + register_task_description("acme-update", |_ty, id: Option<String>| {
> + let id = id.unwrap_or_else(|| "default".to_string());
> + tr!("Update ACME Account - {0}", id)
> + });
> + register_task_description("acme-new-cert", ("", tr!("Order Certificate")));
> + register_task_description("acme-renew-cert", ("", tr!("Renew Certificate")));
> + register_task_description("acme-revoke-cert", ("", tr!("Revoke Certificate")));
> + register_task_description("backup", |_ty, id: Option<String>| {
> + render_datastore_worker_id(id, &tr!("Backup"))
> + });
> + register_task_description(
> + "barcode-label-media",
> + (tr!("Drive"), tr!("Barcode-Label Media")),
> + );
> + register_task_description("catalog-media", (tr!("Drive"), tr!("Catalog Media")));
> + register_task_description(
> + "create-datastore",
> + (tr!("Datastore"), tr!("Create Datastore")),
> + );
> + register_task_description(
> + "delete-datastore",
> + (tr!("Datastore"), tr!("Remove Datastore")),
> + );
> + register_task_description(
> + "delete-namespace",
> + (tr!("Namespace"), tr!("Remove Namespace")),
> + );
> + register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
> + register_task_description("dirremove", (tr!("Directory Storage"), tr!("Remove")));
> + register_task_description("eject-media", (tr!("Drive"), tr!("Eject Media")));
> + register_task_description("format-media", (tr!("Drive"), tr!("Format Media")));
> + register_task_description("forget-group", (tr!("Group"), tr!("Remove Group")));
> + register_task_description(
> + "garbage_collection",
> + (tr!("Datastore"), tr!("Garbage Collect")),
> + );
> + register_task_description("realm-sync", ("Realm", tr!("User Sync")));
> + register_task_description("inventory-update", (tr!("Drive"), tr!("Inventory Update")));
> + register_task_description("label-media", (tr!("Drive"), tr!("Label Media")));
> + register_task_description("load-media", |_ty, id: Option<String>| {
> + render_drive_load_media_id(&id.unwrap_or_default(), &tr!("Load Media"))
> + });
> + register_task_description("logrotate", tr!("Log Rotation"));
> + register_task_description("mount-device", (tr!("Datastore"), tr!("Mount Device")));
> + register_task_description(
> + "mount-sync-jobs",
> + (
> + tr!("Datastore"),
> + tr!("sync jobs handler triggered by mount"),
> + ),
> + );
> + register_task_description("prune", |_ty, id: Option<String>| {
> + render_datastore_worker_id(id, &tr!("Prune"))
> + });
> + register_task_description("prunejob", |_ty, id: Option<String>| {
> + render_prune_job_worker_id(id, &tr!("Prune Job"))
> + });
> + register_task_description("reader", |_ty, id: Option<String>| {
> + render_datastore_worker_id(id, &tr!("Read Objects"))
> + });
> + register_task_description("rewind-media", (tr!("Drive"), tr!("Rewind Media")));
> + register_task_description("s3-refresh", (tr!("Datastore"), tr!("S3 Refresh")));
> + register_task_description("sync", (tr!("Datastore"), tr!("Remote Sync")));
> + register_task_description("syncjob", (tr!("Sync Job"), tr!("Remote Sync")));
> + register_task_description("tape-backup", |_ty, id: Option<String>| {
> + render_tape_backup_id(id, &tr!("Tape Backup"))
> + });
> + register_task_description("tape-backup-job", |_ty, id: Option<String>| {
> + render_tape_backup_id(id, &tr!("Tape Backup Job"))
> + });
> + register_task_description("tape-restore", (tr!("Datastore"), tr!("Tape Restore")));
> + register_task_description("unload-media", (tr!("Drive"), tr!("Unload Media")));
> + register_task_description("unmount-device", (tr!("Datastore"), tr!("Unmount Device")));
> + register_task_description(
> + "verificationjob",
> + (tr!("Verify Job"), tr!("Scheduled Verification")),
> + );
> + register_task_description("verify", (tr!("Datastore"), tr!("Verification")));
> + register_task_description("verify_group", (tr!("Group"), tr!("Verification")));
> + register_task_description("verify_snapshot", (tr!("Snapshot"), tr!("Verification")));
> + register_task_description("wipedisk", (tr!("Device"), tr!("Wipe Disk")));
> + register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
> +}
> +
> +proxmox_schema::const_regex! {
> + DATASTORE_WORKER_ID_REGEX = r"^(\S+?):(\S+?)/(\S+?)(/(.+))?$";
> +}
> +
> +fn render_datastore_worker_id(id: Option<String>, what: &str) -> String {
> + let id = id.as_deref().unwrap_or("unknown");
> +
> + if let Some(cap) = DATASTORE_WORKER_ID_REGEX.captures(id) {
> + let datastore = cap.get(1).map(|m| m.as_str());
> + let res2 = cap.get(2).map(|m| m.as_str());
> + let res3 = cap.get(3).map(|m| m.as_str());
> + let epoch = cap.get(5).map(|m| m.as_str());
> +
> + if let (Some(datastore), Some(res2), Some(res3), Some(epoch)) =
> + (datastore, res2, res3, epoch)
> + {
> + if let Ok(epoch) = i64::from_str_radix(epoch, 16) {
> + let utctime = proxmox_time::epoch_to_rfc3339_utc(epoch).unwrap_or_default();
> + return format!(
> + "{} {} {} {}/{} {}",
> + tr!("Datastore"),
> + datastore,
> + what,
> + res2,
> + res3,
> + utctime
> + );
> + }
> + }
> + }
> +
> + format!("{} {} {}", tr!("Datastore"), id, what)
> +}
this implementation differs a bit from the js one.
if the regex matches but the epoch is `None` we render
'Datastore id what' instead of
'Datastore id what backupgroup'
> +
> +proxmox_schema::const_regex! {
> + PRUNE_JOB_WORKER_ID_REGEX = r"^(\S+?):(\S+)$";
> +}
> +
> +fn render_prune_job_worker_id(id: Option<String>, what: &str) -> String {
> + let id = id.as_deref().unwrap_or("unknown");
> +
> + if let Some(cap) = PRUNE_JOB_WORKER_ID_REGEX.captures(id) {
> + let datastore = cap.get(1).map(|m| m.as_str());
> + let namespace = cap.get(2).map(|m| m.as_str());
> +
> + if let (Some(datastore), Some(namespace)) = (datastore, namespace) {
> + return format!(
> + "{} on {} {} {} {}",
> + what,
> + tr! {"Datastore"},
> + datastore,
> + tr!("Namespace"),
> + namespace
> + );
> + }
> + }
> + return format!("{} on {} {}", what, tr! {"Datastore"}, id);
> +}
> +
> +proxmox_schema::const_regex! {
> + TAPE_WORKER_ID_REGEX = r"^(\S+?):(\S+?):(\S+?)(:(.+))?$";
> +}
> +
> +fn render_tape_backup_id(id: Option<String>, what: &str) -> String {
> + let id = id.as_deref().unwrap_or("unknown");
> +
> + if let Some(cap) = TAPE_WORKER_ID_REGEX.captures(id) {
> + let datastore = cap.get(1).map(|m| m.as_str());
> + let pool = cap.get(2).map(|m| m.as_str());
> + let drive = cap.get(3).map(|m| m.as_str());
> +
> + if let (Some(datastore), Some(pool), Some(drive)) = (datastore, pool, drive) {
> + return format!("{} {} (pool {}, drive {})", what, datastore, pool, drive);
> + }
> + }
> + format!("{} {}", what, id)
this is also a bit different:
on pbs we format them as
'{what} on Datastore {datastore} Namespace {namespace}'
> +}
> +
> +proxmox_schema::const_regex! {
> + DRIVE_LOAD_WORKER_ID_REGEX = r"^(\S+?):(\S+?)$";
> +}
> +
> +fn render_drive_load_media_id(id: &str, what: &str) -> String {
> + if let Some(caps) = DRIVE_LOAD_WORKER_ID_REGEX.captures(id) {
> + let drive = &caps[1];
> + let label = &caps[2];
> + return format!("{} {drive} - {what} '{label}'", tr!("Drive"));
> + }
> +
> + format!("{what} {id}")
> +}
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* [pdm-devel] superseded: [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
` (3 preceding siblings ...)
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 2/2] ui: use task descriptions from yew-comp for PBS and PVE Lukas Wagner
@ 2025-12-18 12:19 ` Lukas Wagner
4 siblings, 0 replies; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 12:19 UTC (permalink / raw)
To: Proxmox Datacenter Manager development discussion
On Thu Dec 18, 2025 at 10:51 AM CET, Lukas Wagner wrote:
>
>
>
> proxmox-yew-comp:
>
> Lukas Wagner (2):
> utils: move task descriptions to a submodule
> task descriptions: add PBS task descriptions
>
> src/utils/mod.rs | 228 +------------------
> src/utils/task_descriptions.rs | 400 +++++++++++++++++++++++++++++++++
> 2 files changed, 412 insertions(+), 216 deletions(-)
> create mode 100644 src/utils/task_descriptions.rs
>
>
> proxmox-datacenter-manager:
>
> Lukas Wagner (2):
> ui: register task descriptions for some native PDM tasks
> ui: use task descriptions from yew-comp for PBS and PVE
>
> ui/src/lib.rs | 2 +-
> ui/src/main.rs | 7 +--
> ui/src/tasks.rs | 122 ++++++++----------------------------------------
> 3 files changed, 25 insertions(+), 106 deletions(-)
>
>
> Summary over all repositories:
> 5 files changed, 437 insertions(+), 322 deletions(-)
superseded by:
https://lore.proxmox.com/all/20251218121902.187674-1-l.wagner@proxmox.com/T/#u
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions
2025-12-18 12:19 ` Dominik Csapak
@ 2025-12-18 13:02 ` Lukas Wagner
2025-12-18 13:24 ` Dominik Csapak
0 siblings, 1 reply; 11+ messages in thread
From: Lukas Wagner @ 2025-12-18 13:02 UTC (permalink / raw)
To: Dominik Csapak,
Proxmox Datacenter Manager development discussion, Lukas Wagner
On Thu Dec 18, 2025 at 1:19 PM CET, Dominik Csapak wrote:
> Looks mostly good to me, some comments inline
>
>
> On 12/18/25 10:51 AM, Lukas Wagner wrote:
>> Tried to make these match the JS ones as closely as possible. Some of
>> these could be improved in the future, but this should then be done in
>> tandem with the JS definitions.
>>
>> Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
>> ---
>> src/utils/task_descriptions.rs | 186 +++++++++++++++++++++++++++++++++
>> 1 file changed, 186 insertions(+)
>>
>> diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
>> index 86525a4..caeb563 100644
>> --- a/src/utils/task_descriptions.rs
>> +++ b/src/utils/task_descriptions.rs
>> @@ -212,3 +212,189 @@ pub fn register_pve_tasks() {
>> register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
>> register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
>> }
>> +
>> +/// Register PBS task descriptions.
>> +pub fn register_pbs_tasks() {
>> + register_task_description("acme-deativate", |_ty, id: Option<String>| {
>> + let id = id.unwrap_or_else(|| "default".to_string());
>> + tr!("Deactivate ACME Account - {0}", id)
>> + });
>> + register_task_description("acme-register", |_ty, id: Option<String>| {
>> + let id = id.unwrap_or_else(|| "default".to_string());
>> + tr!("Register ACME Account - {0}", id)
>> + });
>> + register_task_description("acme-update", |_ty, id: Option<String>| {
>> + let id = id.unwrap_or_else(|| "default".to_string());
>> + tr!("Update ACME Account - {0}", id)
>> + });
>> + register_task_description("acme-new-cert", ("", tr!("Order Certificate")));
>> + register_task_description("acme-renew-cert", ("", tr!("Renew Certificate")));
>> + register_task_description("acme-revoke-cert", ("", tr!("Revoke Certificate")));
>> + register_task_description("backup", |_ty, id: Option<String>| {
>> + render_datastore_worker_id(id, &tr!("Backup"))
>> + });
>> + register_task_description(
>> + "barcode-label-media",
>> + (tr!("Drive"), tr!("Barcode-Label Media")),
>> + );
>> + register_task_description("catalog-media", (tr!("Drive"), tr!("Catalog Media")));
>> + register_task_description(
>> + "create-datastore",
>> + (tr!("Datastore"), tr!("Create Datastore")),
>> + );
>> + register_task_description(
>> + "delete-datastore",
>> + (tr!("Datastore"), tr!("Remove Datastore")),
>> + );
>> + register_task_description(
>> + "delete-namespace",
>> + (tr!("Namespace"), tr!("Remove Namespace")),
>> + );
>> + register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
>> + register_task_description("dirremove", (tr!("Directory Storage"), tr!("Remove")));
>> + register_task_description("eject-media", (tr!("Drive"), tr!("Eject Media")));
>> + register_task_description("format-media", (tr!("Drive"), tr!("Format Media")));
>> + register_task_description("forget-group", (tr!("Group"), tr!("Remove Group")));
>> + register_task_description(
>> + "garbage_collection",
>> + (tr!("Datastore"), tr!("Garbage Collect")),
>> + );
>> + register_task_description("realm-sync", ("Realm", tr!("User Sync")));
>> + register_task_description("inventory-update", (tr!("Drive"), tr!("Inventory Update")));
>> + register_task_description("label-media", (tr!("Drive"), tr!("Label Media")));
>> + register_task_description("load-media", |_ty, id: Option<String>| {
>> + render_drive_load_media_id(&id.unwrap_or_default(), &tr!("Load Media"))
>> + });
>> + register_task_description("logrotate", tr!("Log Rotation"));
>> + register_task_description("mount-device", (tr!("Datastore"), tr!("Mount Device")));
>> + register_task_description(
>> + "mount-sync-jobs",
>> + (
>> + tr!("Datastore"),
>> + tr!("sync jobs handler triggered by mount"),
>> + ),
>> + );
>> + register_task_description("prune", |_ty, id: Option<String>| {
>> + render_datastore_worker_id(id, &tr!("Prune"))
>> + });
>> + register_task_description("prunejob", |_ty, id: Option<String>| {
>> + render_prune_job_worker_id(id, &tr!("Prune Job"))
>> + });
>> + register_task_description("reader", |_ty, id: Option<String>| {
>> + render_datastore_worker_id(id, &tr!("Read Objects"))
>> + });
>> + register_task_description("rewind-media", (tr!("Drive"), tr!("Rewind Media")));
>> + register_task_description("s3-refresh", (tr!("Datastore"), tr!("S3 Refresh")));
>> + register_task_description("sync", (tr!("Datastore"), tr!("Remote Sync")));
>> + register_task_description("syncjob", (tr!("Sync Job"), tr!("Remote Sync")));
>> + register_task_description("tape-backup", |_ty, id: Option<String>| {
>> + render_tape_backup_id(id, &tr!("Tape Backup"))
>> + });
>> + register_task_description("tape-backup-job", |_ty, id: Option<String>| {
>> + render_tape_backup_id(id, &tr!("Tape Backup Job"))
>> + });
>> + register_task_description("tape-restore", (tr!("Datastore"), tr!("Tape Restore")));
>> + register_task_description("unload-media", (tr!("Drive"), tr!("Unload Media")));
>> + register_task_description("unmount-device", (tr!("Datastore"), tr!("Unmount Device")));
>> + register_task_description(
>> + "verificationjob",
>> + (tr!("Verify Job"), tr!("Scheduled Verification")),
>> + );
>> + register_task_description("verify", (tr!("Datastore"), tr!("Verification")));
>> + register_task_description("verify_group", (tr!("Group"), tr!("Verification")));
>> + register_task_description("verify_snapshot", (tr!("Snapshot"), tr!("Verification")));
>> + register_task_description("wipedisk", (tr!("Device"), tr!("Wipe Disk")));
>> + register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
>> +}
>> +
>> +proxmox_schema::const_regex! {
>> + DATASTORE_WORKER_ID_REGEX = r"^(\S+?):(\S+?)/(\S+?)(/(.+))?$";
>> +}
>> +
>> +fn render_datastore_worker_id(id: Option<String>, what: &str) -> String {
>> + let id = id.as_deref().unwrap_or("unknown");
>> +
>> + if let Some(cap) = DATASTORE_WORKER_ID_REGEX.captures(id) {
>> + let datastore = cap.get(1).map(|m| m.as_str());
>> + let res2 = cap.get(2).map(|m| m.as_str());
>> + let res3 = cap.get(3).map(|m| m.as_str());
>> + let epoch = cap.get(5).map(|m| m.as_str());
>> +
>> + if let (Some(datastore), Some(res2), Some(res3), Some(epoch)) =
>> + (datastore, res2, res3, epoch)
>> + {
>> + if let Ok(epoch) = i64::from_str_radix(epoch, 16) {
>> + let utctime = proxmox_time::epoch_to_rfc3339_utc(epoch).unwrap_or_default();
>> + return format!(
>> + "{} {} {} {}/{} {}",
>> + tr!("Datastore"),
>> + datastore,
>> + what,
>> + res2,
>> + res3,
>> + utctime
>> + );
>> + }
>> + }
>> + }
>> +
>> + format!("{} {} {}", tr!("Datastore"), id, what)
>> +}
>
> this implementation differs a bit from the js one.
> if the regex matches but the epoch is `None` we render
>
> 'Datastore id what' instead of
> 'Datastore id what backupgroup'
>
>
>
Ack, thanks!
>> +
>> +proxmox_schema::const_regex! {
>> + PRUNE_JOB_WORKER_ID_REGEX = r"^(\S+?):(\S+)$";
>> +}
>> +
>> +fn render_prune_job_worker_id(id: Option<String>, what: &str) -> String {
>> + let id = id.as_deref().unwrap_or("unknown");
>> +
>> + if let Some(cap) = PRUNE_JOB_WORKER_ID_REGEX.captures(id) {
>> + let datastore = cap.get(1).map(|m| m.as_str());
>> + let namespace = cap.get(2).map(|m| m.as_str());
>> +
>> + if let (Some(datastore), Some(namespace)) = (datastore, namespace) {
>> + return format!(
>> + "{} on {} {} {} {}",
>> + what,
>> + tr! {"Datastore"},
>> + datastore,
>> + tr!("Namespace"),
>> + namespace
>> + );
>> + }
>> + }
>> + return format!("{} on {} {}", what, tr! {"Datastore"}, id);
>> +}
As a reference for my comment down below, the JS version is
render_prune_job_worker_id: function (id, what) {
const res = id.match(/^(\S+?):(\S+)$/);
if (!res) {
return `${what} on Datastore ${id}`;
}
let datastore = res[1],
namespace = res[2];
return `${what} on Datastore ${datastore} Namespace ${namespace}`;
},
>> +
>> +proxmox_schema::const_regex! {
>> + TAPE_WORKER_ID_REGEX = r"^(\S+?):(\S+?):(\S+?)(:(.+))?$";
>> +}
>> +
>> +fn render_tape_backup_id(id: Option<String>, what: &str) -> String {
>> + let id = id.as_deref().unwrap_or("unknown");
>> +
>> + if let Some(cap) = TAPE_WORKER_ID_REGEX.captures(id) {
>> + let datastore = cap.get(1).map(|m| m.as_str());
>> + let pool = cap.get(2).map(|m| m.as_str());
>> + let drive = cap.get(3).map(|m| m.as_str());
>> +
>> + if let (Some(datastore), Some(pool), Some(drive)) = (datastore, pool, drive) {
>> + return format!("{} {} (pool {}, drive {})", what, datastore, pool, drive);
>> + }
>> + }
>> + format!("{} {}", what, id)
>
>
> this is also a bit different:
>
> on pbs we format them as
>
> '{what} on Datastore {datastore} Namespace {namespace}'
>
The JS-impl is
render_tape_backup_id: function (id, what) {
const res = id.match(/^(\S+?):(\S+?):(\S+?)(:(.+))?$/);
if (res) {
let datastore = res[1];
let pool = res[2];
let drive = res[3];
return `${what} ${datastore} (pool ${pool}, drive ${drive})`;
}
return `${what} ${id}`;
},
so I think my version should be correct?
Did you mean the formatting for the prune job?
I also double checked this one, seems correct to me.
Keep in mind that the logic is inverted in the JS code.
But maybe I'm missing something :)
>> +}
>> +
>> +proxmox_schema::const_regex! {
>> + DRIVE_LOAD_WORKER_ID_REGEX = r"^(\S+?):(\S+?)$";
>> +}
>> +
>> +fn render_drive_load_media_id(id: &str, what: &str) -> String {
>> + if let Some(caps) = DRIVE_LOAD_WORKER_ID_REGEX.captures(id) {
>> + let drive = &caps[1];
>> + let label = &caps[2];
>> + return format!("{} {drive} - {what} '{label}'", tr!("Drive"));
>> + }
>> +
>> + format!("{what} {id}")
>> +}
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions
2025-12-18 13:02 ` Lukas Wagner
@ 2025-12-18 13:24 ` Dominik Csapak
0 siblings, 0 replies; 11+ messages in thread
From: Dominik Csapak @ 2025-12-18 13:24 UTC (permalink / raw)
To: Lukas Wagner, Proxmox Datacenter Manager development discussion
On 12/18/25 2:02 PM, Lukas Wagner wrote:
> On Thu Dec 18, 2025 at 1:19 PM CET, Dominik Csapak wrote:
>> Looks mostly good to me, some comments inline
>>
>>
>> On 12/18/25 10:51 AM, Lukas Wagner wrote:
>>> Tried to make these match the JS ones as closely as possible. Some of
>>> these could be improved in the future, but this should then be done in
>>> tandem with the JS definitions.
>>>
>>> Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
>>> ---
>>> src/utils/task_descriptions.rs | 186 +++++++++++++++++++++++++++++++++
>>> 1 file changed, 186 insertions(+)
>>>
>>> diff --git a/src/utils/task_descriptions.rs b/src/utils/task_descriptions.rs
>>> index 86525a4..caeb563 100644
>>> --- a/src/utils/task_descriptions.rs
>>> +++ b/src/utils/task_descriptions.rs
>>> @@ -212,3 +212,189 @@ pub fn register_pve_tasks() {
>>> register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
>>> register_task_description("zfsremove", ("ZFS Pool", tr!("Remove")));
>>> }
>>> +
>>> +/// Register PBS task descriptions.
>>> +pub fn register_pbs_tasks() {
>>> + register_task_description("acme-deativate", |_ty, id: Option<String>| {
>>> + let id = id.unwrap_or_else(|| "default".to_string());
>>> + tr!("Deactivate ACME Account - {0}", id)
>>> + });
>>> + register_task_description("acme-register", |_ty, id: Option<String>| {
>>> + let id = id.unwrap_or_else(|| "default".to_string());
>>> + tr!("Register ACME Account - {0}", id)
>>> + });
>>> + register_task_description("acme-update", |_ty, id: Option<String>| {
>>> + let id = id.unwrap_or_else(|| "default".to_string());
>>> + tr!("Update ACME Account - {0}", id)
>>> + });
>>> + register_task_description("acme-new-cert", ("", tr!("Order Certificate")));
>>> + register_task_description("acme-renew-cert", ("", tr!("Renew Certificate")));
>>> + register_task_description("acme-revoke-cert", ("", tr!("Revoke Certificate")));
>>> + register_task_description("backup", |_ty, id: Option<String>| {
>>> + render_datastore_worker_id(id, &tr!("Backup"))
>>> + });
>>> + register_task_description(
>>> + "barcode-label-media",
>>> + (tr!("Drive"), tr!("Barcode-Label Media")),
>>> + );
>>> + register_task_description("catalog-media", (tr!("Drive"), tr!("Catalog Media")));
>>> + register_task_description(
>>> + "create-datastore",
>>> + (tr!("Datastore"), tr!("Create Datastore")),
>>> + );
>>> + register_task_description(
>>> + "delete-datastore",
>>> + (tr!("Datastore"), tr!("Remove Datastore")),
>>> + );
>>> + register_task_description(
>>> + "delete-namespace",
>>> + (tr!("Namespace"), tr!("Remove Namespace")),
>>> + );
>>> + register_task_description("dircreate", (tr!("Directory Storage"), tr!("Create")));
>>> + register_task_description("dirremove", (tr!("Directory Storage"), tr!("Remove")));
>>> + register_task_description("eject-media", (tr!("Drive"), tr!("Eject Media")));
>>> + register_task_description("format-media", (tr!("Drive"), tr!("Format Media")));
>>> + register_task_description("forget-group", (tr!("Group"), tr!("Remove Group")));
>>> + register_task_description(
>>> + "garbage_collection",
>>> + (tr!("Datastore"), tr!("Garbage Collect")),
>>> + );
>>> + register_task_description("realm-sync", ("Realm", tr!("User Sync")));
>>> + register_task_description("inventory-update", (tr!("Drive"), tr!("Inventory Update")));
>>> + register_task_description("label-media", (tr!("Drive"), tr!("Label Media")));
>>> + register_task_description("load-media", |_ty, id: Option<String>| {
>>> + render_drive_load_media_id(&id.unwrap_or_default(), &tr!("Load Media"))
>>> + });
>>> + register_task_description("logrotate", tr!("Log Rotation"));
>>> + register_task_description("mount-device", (tr!("Datastore"), tr!("Mount Device")));
>>> + register_task_description(
>>> + "mount-sync-jobs",
>>> + (
>>> + tr!("Datastore"),
>>> + tr!("sync jobs handler triggered by mount"),
>>> + ),
>>> + );
>>> + register_task_description("prune", |_ty, id: Option<String>| {
>>> + render_datastore_worker_id(id, &tr!("Prune"))
>>> + });
>>> + register_task_description("prunejob", |_ty, id: Option<String>| {
>>> + render_prune_job_worker_id(id, &tr!("Prune Job"))
>>> + });
>>> + register_task_description("reader", |_ty, id: Option<String>| {
>>> + render_datastore_worker_id(id, &tr!("Read Objects"))
>>> + });
>>> + register_task_description("rewind-media", (tr!("Drive"), tr!("Rewind Media")));
>>> + register_task_description("s3-refresh", (tr!("Datastore"), tr!("S3 Refresh")));
>>> + register_task_description("sync", (tr!("Datastore"), tr!("Remote Sync")));
>>> + register_task_description("syncjob", (tr!("Sync Job"), tr!("Remote Sync")));
>>> + register_task_description("tape-backup", |_ty, id: Option<String>| {
>>> + render_tape_backup_id(id, &tr!("Tape Backup"))
>>> + });
>>> + register_task_description("tape-backup-job", |_ty, id: Option<String>| {
>>> + render_tape_backup_id(id, &tr!("Tape Backup Job"))
>>> + });
>>> + register_task_description("tape-restore", (tr!("Datastore"), tr!("Tape Restore")));
>>> + register_task_description("unload-media", (tr!("Drive"), tr!("Unload Media")));
>>> + register_task_description("unmount-device", (tr!("Datastore"), tr!("Unmount Device")));
>>> + register_task_description(
>>> + "verificationjob",
>>> + (tr!("Verify Job"), tr!("Scheduled Verification")),
>>> + );
>>> + register_task_description("verify", (tr!("Datastore"), tr!("Verification")));
>>> + register_task_description("verify_group", (tr!("Group"), tr!("Verification")));
>>> + register_task_description("verify_snapshot", (tr!("Snapshot"), tr!("Verification")));
>>> + register_task_description("wipedisk", (tr!("Device"), tr!("Wipe Disk")));
>>> + register_task_description("zfscreate", (tr!("ZFS Storage"), tr!("Create")));
>>> +}
>>> +
>>> +proxmox_schema::const_regex! {
>>> + DATASTORE_WORKER_ID_REGEX = r"^(\S+?):(\S+?)/(\S+?)(/(.+))?$";
>>> +}
>>> +
>>> +fn render_datastore_worker_id(id: Option<String>, what: &str) -> String {
>>> + let id = id.as_deref().unwrap_or("unknown");
>>> +
>>> + if let Some(cap) = DATASTORE_WORKER_ID_REGEX.captures(id) {
>>> + let datastore = cap.get(1).map(|m| m.as_str());
>>> + let res2 = cap.get(2).map(|m| m.as_str());
>>> + let res3 = cap.get(3).map(|m| m.as_str());
>>> + let epoch = cap.get(5).map(|m| m.as_str());
>>> +
>>> + if let (Some(datastore), Some(res2), Some(res3), Some(epoch)) =
>>> + (datastore, res2, res3, epoch)
>>> + {
>>> + if let Ok(epoch) = i64::from_str_radix(epoch, 16) {
>>> + let utctime = proxmox_time::epoch_to_rfc3339_utc(epoch).unwrap_or_default();
>>> + return format!(
>>> + "{} {} {} {}/{} {}",
>>> + tr!("Datastore"),
>>> + datastore,
>>> + what,
>>> + res2,
>>> + res3,
>>> + utctime
>>> + );
>>> + }
>>> + }
>>> + }
>>> +
>>> + format!("{} {} {}", tr!("Datastore"), id, what)
>>> +}
>>
>> this implementation differs a bit from the js one.
>> if the regex matches but the epoch is `None` we render
>>
>> 'Datastore id what' instead of
>> 'Datastore id what backupgroup'
>>
>>
>>
>
> Ack, thanks!
>
>>> +
>>> +proxmox_schema::const_regex! {
>>> + PRUNE_JOB_WORKER_ID_REGEX = r"^(\S+?):(\S+)$";
>>> +}
>>> +
>>> +fn render_prune_job_worker_id(id: Option<String>, what: &str) -> String {
>>> + let id = id.as_deref().unwrap_or("unknown");
>>> +
>>> + if let Some(cap) = PRUNE_JOB_WORKER_ID_REGEX.captures(id) {
>>> + let datastore = cap.get(1).map(|m| m.as_str());
>>> + let namespace = cap.get(2).map(|m| m.as_str());
>>> +
>>> + if let (Some(datastore), Some(namespace)) = (datastore, namespace) {
>>> + return format!(
>>> + "{} on {} {} {} {}",
>>> + what,
>>> + tr! {"Datastore"},
>>> + datastore,
>>> + tr!("Namespace"),
>>> + namespace
>>> + );
>>> + }
>>> + }
>>> + return format!("{} on {} {}", what, tr! {"Datastore"}, id);
>>> +}
>
> As a reference for my comment down below, the JS version is
>
> render_prune_job_worker_id: function (id, what) {
> const res = id.match(/^(\S+?):(\S+)$/);
> if (!res) {
> return `${what} on Datastore ${id}`;
> }
> let datastore = res[1],
> namespace = res[2];
> return `${what} on Datastore ${datastore} Namespace ${namespace}`;
> },
>
>
>>> +
>>> +proxmox_schema::const_regex! {
>>> + TAPE_WORKER_ID_REGEX = r"^(\S+?):(\S+?):(\S+?)(:(.+))?$";
>>> +}
>>> +
>>> +fn render_tape_backup_id(id: Option<String>, what: &str) -> String {
>>> + let id = id.as_deref().unwrap_or("unknown");
>>> +
>>> + if let Some(cap) = TAPE_WORKER_ID_REGEX.captures(id) {
>>> + let datastore = cap.get(1).map(|m| m.as_str());
>>> + let pool = cap.get(2).map(|m| m.as_str());
>>> + let drive = cap.get(3).map(|m| m.as_str());
>>> +
>>> + if let (Some(datastore), Some(pool), Some(drive)) = (datastore, pool, drive) {
>>> + return format!("{} {} (pool {}, drive {})", what, datastore, pool, drive);
>>> + }
>>> + }
>>> + format!("{} {}", what, id)
>>
>>
>> this is also a bit different:
>>
>> on pbs we format them as
>>
>> '{what} on Datastore {datastore} Namespace {namespace}'
>>
>
> The JS-impl is
>
> render_tape_backup_id: function (id, what) {
> const res = id.match(/^(\S+?):(\S+?):(\S+?)(:(.+))?$/);
> if (res) {
> let datastore = res[1];
> let pool = res[2];
> let drive = res[3];
> return `${what} ${datastore} (pool ${pool}, drive ${drive})`;
> }
> return `${what} ${id}`;
> },
>
>
> so I think my version should be correct?
>
>
> Did you mean the formatting for the prune job?
> I also double checked this one, seems correct to me.
> Keep in mind that the logic is inverted in the JS code.
>
> But maybe I'm missing something :)
>
yeah, i looked in the wrong place when trying to find which function it
was to compare... oops and sorry for the noise
>
>>> +}
>>> +
>>> +proxmox_schema::const_regex! {
>>> + DRIVE_LOAD_WORKER_ID_REGEX = r"^(\S+?):(\S+?)$";
>>> +}
>>> +
>>> +fn render_drive_load_media_id(id: &str, what: &str) -> String {
>>> + if let Some(caps) = DRIVE_LOAD_WORKER_ID_REGEX.captures(id) {
>>> + let drive = &caps[1];
>>> + let label = &caps[2];
>>> + return format!("{} {drive} - {what} '{label}'", tr!("Drive"));
>>> + }
>>> +
>>> + format!("{what} {id}")
>>> +}
>
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-12-18 13:23 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-18 9:51 [pdm-devel] [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 1/2] utils: move task descriptions to a submodule Lukas Wagner
2025-12-18 11:49 ` Dominik Csapak
2025-12-18 12:05 ` Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH proxmox-yew-comp 2/2] task descriptions: add PBS task descriptions Lukas Wagner
2025-12-18 12:19 ` Dominik Csapak
2025-12-18 13:02 ` Lukas Wagner
2025-12-18 13:24 ` Dominik Csapak
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 1/2] ui: register task descriptions for some native PDM tasks Lukas Wagner
2025-12-18 9:51 ` [pdm-devel] [PATCH datacenter-manager 2/2] ui: use task descriptions from yew-comp for PBS and PVE Lukas Wagner
2025-12-18 12:19 ` [pdm-devel] superseded: [PATCH datacenter-manager/proxmox-yew-comp 0/4] move task description table to yew-comp Lukas Wagner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.