all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes
  2026-10-09 14:53 [PATCH proxmox{,-backup} v3 00/10] fix #7904: Implement Enable checkboxes for all jobs Jonas Theisen
@ 2026-10-09 14:53 ` Jonas Theisen
  0 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:53 UTC (permalink / raw)
  To: pbs-devel

This commit aligns the already existing "Enabled" checkbox in
the Prune Job Edit window to the other checkboxes.

Meaning a reword from "Enabled" to "Enable" as it is more common
throghout the UI and the disabling of the schedule field if the
checkbox is off.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/window/PruneJobEdit.js | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/www/window/PruneJobEdit.js b/www/window/PruneJobEdit.js
index a3dafde21..2eb8c7129 100644
--- a/www/window/PruneJobEdit.js
+++ b/www/window/PruneJobEdit.js
@@ -43,6 +43,15 @@ Ext.define('PBS.window.PruneJobEdit', {
         },
     },
 
+    setValues: function (values) {
+        let me = this;
+
+        if (!values.schedule || values.schedule === '') {
+            values.disable = true;
+        }
+        me.callParent([values]);
+    },
+
     items: {
         xtype: 'inputpanel',
         onGetValues: function (values) {
@@ -118,11 +127,19 @@ Ext.define('PBS.window.PruneJobEdit', {
             },
             {
                 xtype: 'proxmoxcheckbox',
-                fieldLabel: gettext('Enabled'),
+                fieldLabel: gettext('Enable'),
                 name: 'enable',
                 uncheckedValue: 0,
                 defaultValue: 1,
                 checked: true,
+                listeners: {
+                    change: function (field, enabled) {
+                        let me = this;
+                        let view = me.up('pbsPruneJobEdit');
+                        let schedule = view.down('field[name=schedule]');
+                        schedule.setDisabled(!enabled);
+                    },
+                },
             },
         ],
 
-- 
2.47.3





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

* [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes
@ 2026-10-09 14:54 Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 04/10] api: prune job: align prune job schedule to other jobs Jonas Theisen
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

This commit aligns the already existing "Enabled" checkbox in
the Prune Job Edit window to the other checkboxes.

Meaning a reword from "Enabled" to "Enable" as it is more common
throghout the UI and the disabling of the schedule field if the
checkbox is off.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/window/PruneJobEdit.js | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/www/window/PruneJobEdit.js b/www/window/PruneJobEdit.js
index a3dafde21..2eb8c7129 100644
--- a/www/window/PruneJobEdit.js
+++ b/www/window/PruneJobEdit.js
@@ -43,6 +43,15 @@ Ext.define('PBS.window.PruneJobEdit', {
         },
     },
 
+    setValues: function (values) {
+        let me = this;
+
+        if (!values.schedule || values.schedule === '') {
+            values.disable = true;
+        }
+        me.callParent([values]);
+    },
+
     items: {
         xtype: 'inputpanel',
         onGetValues: function (values) {
@@ -118,11 +127,19 @@ Ext.define('PBS.window.PruneJobEdit', {
             },
             {
                 xtype: 'proxmoxcheckbox',
-                fieldLabel: gettext('Enabled'),
+                fieldLabel: gettext('Enable'),
                 name: 'enable',
                 uncheckedValue: 0,
                 defaultValue: 1,
                 checked: true,
+                listeners: {
+                    change: function (field, enabled) {
+                        let me = this;
+                        let view = me.up('pbsPruneJobEdit');
+                        let schedule = view.down('field[name=schedule]');
+                        schedule.setDisabled(!enabled);
+                    },
+                },
             },
         ],
 
-- 
2.47.3





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

* [PATCH proxmox-backup v3 04/10] api: prune job: align prune job schedule to other jobs
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 05/10] fix #7904: api: implement "disable" for {sync,verify,tape,GC} jobs Jonas Theisen
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

To allow creation of prune jobs without a schedule the parameter
needs to be optional and be able to handle no content.

This is already the case for the schedule parameters of the other
job types, so this patch aligns the prune job schedules by using
an Option<String> instead of a plain String.

This patch also integrates the API check for disable = true if no
schedule is provided.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 src/api2/admin/prune.rs                          |  2 +-
 src/api2/config/datastore.rs                     |  2 +-
 src/api2/config/prune.rs                         | 16 +++++++++++-----
 src/bin/proxmox-backup-proxy.rs                  |  9 +++++++--
 src/bin/proxmox_backup_manager/migrate_config.rs |  2 +-
 5 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/api2/admin/prune.rs b/src/api2/admin/prune.rs
index 0846d8893..784b0ac6f 100644
--- a/src/api2/admin/prune.rs
+++ b/src/api2/admin/prune.rs
@@ -73,7 +73,7 @@ pub fn list_prune_jobs(
     let mut list = Vec::new();
 
     for job in job_config_iter {
-        let mut status = compute_schedule_status("prunejob", &job.id, Some(&job.schedule))?;
+        let mut status = compute_schedule_status("prunejob", &job.id, job.schedule.as_deref())?;
         if job.disable {
             status.next_run = None;
         }
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index e7028480c..a8b003601 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -321,7 +321,7 @@ pub fn create_datastore(
                 store: config.name.clone(),
                 comment: None,
                 disable: false,
-                schedule: schedule.clone(),
+                schedule: Some(schedule.clone()),
                 options: PruneJobOptions {
                     keep: config.keep.clone(),
                     max_depth: None,
diff --git a/src/api2/config/prune.rs b/src/api2/config/prune.rs
index 91d2324f9..3186fad64 100644
--- a/src/api2/config/prune.rs
+++ b/src/api2/config/prune.rs
@@ -1,4 +1,4 @@
-use anyhow::Error;
+use anyhow::{Error, format_err};
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
 
@@ -112,6 +112,13 @@ pub fn create_prune_job(
 
     user_info.check_privs(&auth_id, &config.acl_path(), PRIV_DATASTORE_MODIFY, true)?;
 
+    if !config.disable && config.schedule.is_none() {
+        param_bail!(
+            "schedule",
+            format_err!("no schedule provided but job also not disabled")
+        );
+    }
+
     do_create_prune_job(config)
 }
 
@@ -284,10 +291,9 @@ pub fn update_prune_job(
         user_info.check_privs(&auth_id, &data.acl_path(), PRIV_DATASTORE_MODIFY, true)?;
     }
 
-    let mut schedule_changed = false;
-    if let Some(schedule) = update.schedule {
-        schedule_changed = data.schedule != schedule;
-        data.schedule = schedule;
+    let schedule_changed = data.schedule != update.schedule;
+    if update.schedule.is_some() {
+        data.schedule = update.schedule;
     }
 
     if let Some(max_depth) = update.options.max_depth {
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index 22abfdbdb..c66cffeb4 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -641,9 +641,14 @@ async fn schedule_datastore_prune_jobs() {
             continue;
         }
 
+        let event_str = match job_config.schedule {
+            Some(event_str) => event_str,
+            None => continue,
+        };
+
         let worker_type = "prunejob";
         let auth_id = Authid::root_auth_id().clone();
-        if check_schedule(worker_type, &job_config.schedule, &job_id) {
+        if check_schedule(worker_type, &event_str, &job_id) {
             let job = match Job::new(worker_type, &job_id) {
                 Ok(job) => job,
                 Err(_) => continue, // could not get lock
@@ -653,7 +658,7 @@ async fn schedule_datastore_prune_jobs() {
                 job_config.options,
                 job_config.store,
                 &auth_id,
-                Some(job_config.schedule),
+                Some(event_str),
             ) {
                 eprintln!("unable to start datastore prune job {job_id} - {err}");
             }
diff --git a/src/bin/proxmox_backup_manager/migrate_config.rs b/src/bin/proxmox_backup_manager/migrate_config.rs
index 69f908dc5..b48d53104 100644
--- a/src/bin/proxmox_backup_manager/migrate_config.rs
+++ b/src/bin/proxmox_backup_manager/migrate_config.rs
@@ -84,7 +84,7 @@ pub(crate) fn update_to_prune_jobs_config() -> Result<(), Error> {
             store: store.clone(),
             disable: false,
             comment: None,
-            schedule,
+            schedule: Some(schedule),
             options,
         };
 
-- 
2.47.3





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

* [PATCH proxmox-backup v3 05/10] fix #7904: api: implement "disable" for {sync,verify,tape,GC} jobs
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 04/10] api: prune job: align prune job schedule to other jobs Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 06/10] fix #7904: ui: job edit: introduce "Enable" checkbox " Jonas Theisen
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

To allow users to disable jobs without having to remove the
schedule this patch introduces the "disable" parameter.

This can also be used to create jobs which are supposed to
be run only manually, since with the "disable" parameter
set to true, no schedule is required.

The create endpoint for the respective jobs also now raises
a paramter error if schedule is not set but disable is also
not set i.e. false.
Updates are still allowed to not prevent unrelated config updates.

The value is inserted into the job config and honored by
the scheduler by skipping disabled jobs altogether.
For GC jobs the value is inserted into the datastore config.

If the value is not present in a job config it is assumed the job
is to be enabled for backwards compatibility and to reduce
config-bloat.

Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=7904
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 src/api2/admin/datastore.rs        |  1 +
 src/api2/admin/gc.rs               | 12 +++++++++++-
 src/api2/admin/sync.rs             |  7 ++++++-
 src/api2/admin/verify.rs           |  7 ++++++-
 src/api2/config/datastore.rs       |  9 +++++++++
 src/api2/config/sync.rs            | 18 +++++++++++++++++-
 src/api2/config/tape_backup_job.rs |  9 ++++++++-
 src/api2/config/verify.rs          | 17 ++++++++++++++++-
 src/api2/tape/backup.rs            |  6 +++++-
 src/bin/proxmox-backup-proxy.rs    | 16 ++++++++++++++++
 10 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index 3367fb2c1..543f3ecf4 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -1264,6 +1264,7 @@ pub(crate) fn garbage_collection_status_unchecked(
     let mut info = GarbageCollectionJobStatus {
         store: store.clone(),
         schedule: store_config.gc_schedule,
+        disable: store_config.gc_disable,
         ..Default::default()
     };
 
diff --git a/src/api2/admin/gc.rs b/src/api2/admin/gc.rs
index 3c8bc2946..db79a2581 100644
--- a/src/api2/admin/gc.rs
+++ b/src/api2/admin/gc.rs
@@ -58,7 +58,17 @@ pub fn list_all_gc_jobs(
             .collect::<Vec<_>>(),
     };
 
-    Ok(gc_info)
+    let mut list = Vec::new();
+
+    for mut job in gc_info {
+        if job.disable {
+            job.next_run = None;
+        }
+
+        list.push(job);
+    }
+
+    Ok(list)
 }
 
 const GC_ROUTER: Router = Router::new().get(&API_METHOD_LIST_ALL_GC_JOBS);
diff --git a/src/api2/admin/sync.rs b/src/api2/admin/sync.rs
index 1799f51c0..10649ab66 100644
--- a/src/api2/admin/sync.rs
+++ b/src/api2/admin/sync.rs
@@ -112,7 +112,12 @@ pub fn list_config_sync_jobs(
             continue;
         }
 
-        let status = compute_schedule_status("syncjob", &job.id, job.schedule.as_deref())?;
+        let mut status =
+            compute_schedule_status("syncjob", &job.id, job.schedule.as_deref())?;
+
+        if job.disable {
+            status.next_run = None;
+        }
 
         list.push(SyncJobStatus {
             config: job,
diff --git a/src/api2/admin/verify.rs b/src/api2/admin/verify.rs
index 80659ebe2..413ee79d4 100644
--- a/src/api2/admin/verify.rs
+++ b/src/api2/admin/verify.rs
@@ -73,7 +73,12 @@ pub fn list_verification_jobs(
     let mut list = Vec::new();
 
     for job in job_config_iter {
-        let status = compute_schedule_status("verificationjob", &job.id, job.schedule.as_deref())?;
+        let mut status =
+            compute_schedule_status("verificationjob", &job.id, job.schedule.as_deref())?;
+
+        if job.disable {
+            status.next_run = None;
+        }
 
         list.push(VerificationJobStatus {
             config: job,
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index a8b003601..f3644149e 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -406,6 +406,8 @@ pub fn read_datastore(
 pub enum DeletableProperty {
     /// Delete the comment property.
     Comment,
+    /// Unset the disable flag.
+    GcDisable,
     /// Delete the garbage collection schedule.
     GcSchedule,
     /// Delete the gc-on-unmount property.
@@ -493,6 +495,9 @@ pub fn update_datastore(
                 DeletableProperty::Comment => {
                     data.comment = None;
                 }
+                DeletableProperty::GcDisable => {
+                    data.gc_disable = false;
+                }
                 DeletableProperty::GcSchedule => {
                     data.gc_schedule = None;
                 }
@@ -571,6 +576,10 @@ pub fn update_datastore(
         data.gc_on_unmount = update.gc_on_unmount;
     }
 
+    if let Some(value) = update.gc_disable {
+        data.gc_disable = value;
+    }
+
     macro_rules! prune_disabled {
         ($(($param:literal, $($member:tt)+)),+) => {
             $(
diff --git a/src/api2/config/sync.rs b/src/api2/config/sync.rs
index beed6e7e3..e5c23dcd0 100644
--- a/src/api2/config/sync.rs
+++ b/src/api2/config/sync.rs
@@ -1,5 +1,5 @@
 use ::serde::{Deserialize, Serialize};
-use anyhow::{Error, bail};
+use anyhow::{Error, bail, format_err};
 use pbs_api_types::SyncDirection;
 use serde_json::Value;
 
@@ -306,6 +306,13 @@ pub fn create_sync_job(
         }
     }
 
+    if !config.disable && config.schedule.is_none() {
+        param_bail!(
+            "schedule",
+            format_err!("no schedule provided but job also not disabled")
+        );
+    }
+
     let (mut section_config, _digest) = sync::config()?;
 
     if section_config.sections.contains_key(&config.id) {
@@ -383,6 +390,8 @@ pub enum DeletableProperty {
     Owner,
     /// Delete the comment property.
     Comment,
+    /// Unset the disable flag.
+    Disable,
     /// Delete the job schedule.
     Schedule,
     /// Delete the remove-vanished flag.
@@ -499,6 +508,9 @@ pub fn update_sync_job(
                 DeletableProperty::Comment => {
                     data.comment = None;
                 }
+                DeletableProperty::Disable => {
+                    data.disable = false;
+                }
                 DeletableProperty::Schedule => {
                     data.schedule = None;
                 }
@@ -702,6 +714,9 @@ pub fn update_sync_job(
     if update.schedule.is_some() {
         data.schedule = update.schedule;
     }
+    if let Some(value) = update.disable {
+        data.disable = value;
+    }
     if update.remove_vanished.is_some() {
         data.remove_vanished = update.remove_vanished;
     }
@@ -847,6 +862,7 @@ acl:1:/remote/remote1/remotestore1:write@pbs:RemoteSyncOperator
         max_depth: None,
         group_filter: None,
         schedule: None,
+        disable: false,
         limit: pbs_api_types::RateLimitConfig::default(), // no limit
         transfer_last: None,
         encrypted_only: None,
diff --git a/src/api2/config/tape_backup_job.rs b/src/api2/config/tape_backup_job.rs
index 4bfc7f871..bb77abec5 100644
--- a/src/api2/config/tape_backup_job.rs
+++ b/src/api2/config/tape_backup_job.rs
@@ -1,5 +1,5 @@
 use ::serde::{Deserialize, Serialize};
-use anyhow::Error;
+use anyhow::{Error, format_err};
 use serde_json::Value;
 
 use proxmox_router::{Permission, Router, RpcEnvironment, http_bail};
@@ -79,6 +79,13 @@ pub fn create_tape_backup_job(
 
     check_tape_backup_permission(&auth_id, &job.setup)?;
 
+    if !job.disable && job.schedule.is_none() {
+        param_bail!(
+            "schedule",
+            format_err!("no schedule provided but job also not disabled")
+        );
+    }
+
     let _lock = pbs_config::tape_job::lock()?;
 
     let (mut config, _digest) = pbs_config::tape_job::config()?;
diff --git a/src/api2/config/verify.rs b/src/api2/config/verify.rs
index 35be9b175..afd0c3c85 100644
--- a/src/api2/config/verify.rs
+++ b/src/api2/config/verify.rs
@@ -1,5 +1,5 @@
 use ::serde::{Deserialize, Serialize};
-use anyhow::Error;
+use anyhow::{Error, format_err};
 use serde_json::Value;
 
 use proxmox_router::{Permission, Router, RpcEnvironment, http_bail};
@@ -80,6 +80,13 @@ pub fn create_verification_job(
 
     user_info.check_privs(&auth_id, &config.acl_path(), PRIV_DATASTORE_VERIFY, false)?;
 
+    if !config.disable && config.schedule.is_none() {
+        param_bail!(
+            "schedule",
+            format_err!("no schedule provided but job also not disabled")
+        );
+    }
+
     let _lock = verify::lock_config()?;
 
     let (mut section_config, _digest) = verify::config()?;
@@ -140,6 +147,8 @@ pub enum DeletableProperty {
     IgnoreVerified,
     /// Delete the comment property.
     Comment,
+    /// Unset the disable flag.
+    Disable,
     /// Delete the job schedule.
     Schedule,
     /// Delete outdated after property.
@@ -220,6 +229,9 @@ pub fn update_verification_job(
                 DeletableProperty::Comment => {
                     data.comment = None;
                 }
+                DeletableProperty::Disable => {
+                    data.disable = false;
+                }
                 DeletableProperty::Schedule => {
                     data.schedule = None;
                 }
@@ -262,6 +274,9 @@ pub fn update_verification_job(
     if update.schedule.is_some() {
         data.schedule = update.schedule;
     }
+    if let Some(value) = update.disable {
+        data.disable = value;
+    }
     if let Some(ns) = update.ns {
         if !ns.is_root() {
             data.ns = Some(ns);
diff --git a/src/api2/tape/backup.rs b/src/api2/tape/backup.rs
index c0a4ca65b..f86ab2e47 100644
--- a/src/api2/tape/backup.rs
+++ b/src/api2/tape/backup.rs
@@ -83,7 +83,11 @@ pub fn list_tape_backup_jobs(
 
         let status = compute_schedule_status("tape-backup-job", &job.id, job.schedule.as_deref())?;
 
-        let next_run = status.next_run.unwrap_or(current_time);
+        let next_run = if job.disable {
+            0
+        } else {
+            status.next_run.unwrap_or(current_time)
+        };
 
         let mut next_media_label = None;
 
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index c66cffeb4..ce2629d0e 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -537,6 +537,10 @@ async fn schedule_datastore_garbage_collection() {
             }
         };
 
+        if store_config.gc_disable {
+            continue;
+        }
+
         let event_str = match store_config.gc_schedule {
             Some(event_str) => event_str,
             None => continue,
@@ -689,6 +693,10 @@ async fn schedule_datastore_sync_jobs() {
             None => continue,
         };
 
+        if job_config.disable {
+            continue;
+        }
+
         let worker_type = "syncjob";
         if check_schedule(worker_type, &event_str, &job_id) {
             let job = match Job::new(worker_type, &job_id) {
@@ -725,6 +733,10 @@ async fn schedule_datastore_verify_jobs() {
             None => continue,
         };
 
+        if job_config.disable {
+            continue;
+        }
+
         let worker_type = "verificationjob";
         let auth_id = Authid::root_auth_id().clone();
         if check_schedule(worker_type, &event_str, &job_id) {
@@ -761,6 +773,10 @@ async fn schedule_tape_backup_jobs() {
             None => continue,
         };
 
+        if job_config.disable {
+            continue;
+        }
+
         let worker_type = "tape-backup-job";
         let auth_id = Authid::root_auth_id().clone();
         if check_schedule(worker_type, &event_str, &job_id) {
-- 
2.47.3





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

* [PATCH proxmox-backup v3 06/10] fix #7904: ui: job edit: introduce "Enable" checkbox for {sync,verify,tape,GC} jobs
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 04/10] api: prune job: align prune job schedule to other jobs Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 05/10] fix #7904: api: implement "disable" for {sync,verify,tape,GC} jobs Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 07/10] ui: improve visibility of disabled {sync,verify,tape,GC,prune} jobs on the overview page Jonas Theisen
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

This allow users to disable jobs from the UI using the "disable"
API paramter.

This also disallows the schedule from being empty since disabling jobs
can now be done with the "disable" parameter.

To avoid user confusion and remain backwards compatible, the setValues
function automatically sets the "disable" parameter to true if
the schedule is currently empty i.e. the job is disabled.

Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=7904
Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/tape/window/TapeBackupJob.js | 40 ++++++++++++++++++++++--
 www/window/GCJobEdit.js          | 52 +++++++++++++++++++++++++++++---
 www/window/SyncJobEdit.js        | 36 ++++++++++++++++++++--
 www/window/VerifyJobEdit.js      | 40 ++++++++++++++++++++++--
 4 files changed, 157 insertions(+), 11 deletions(-)

diff --git a/www/tape/window/TapeBackupJob.js b/www/tape/window/TapeBackupJob.js
index ad03b6076..833672076 100644
--- a/www/tape/window/TapeBackupJob.js
+++ b/www/tape/window/TapeBackupJob.js
@@ -46,6 +46,14 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
         },
     },
 
+    setValues: function (values) {
+        let me = this;
+        if (!values.schedule || values.schedule === '') {
+            values.disable = true;
+        }
+        me.callParent([values]);
+    },
+
     items: {
         xtype: 'tabpanel',
         bodyPadding: 10,
@@ -66,6 +74,16 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
                         delete values.delete;
                     }
 
+                    values.disable = !values.enable;
+                    delete values.enable;
+
+                    return values;
+                },
+                onSetValues: function (values) {
+                    let _me = this;
+                    values.enable = !values.disable;
+                    delete values.disable;
+
                     return values;
                 },
                 cbind: {
@@ -112,13 +130,31 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', {
                 ],
 
                 column2: [
+                    {
+                        xtype: 'proxmoxcheckbox',
+                        fieldLabel: gettext('Enable'),
+                        name: 'enable',
+                        autoEl: {
+                            tag: 'div',
+                            'data-qtip': gettext('Enable scheduled execution of this task.'),
+                        },
+                        listeners: {
+                            change: function (field, enabled) {
+                                let me = this;
+                                let view = me.up('pbsTapeBackupJobEdit');
+                                let schedule = view.down('field[name=schedule]');
+                                schedule.setDisabled(!enabled);
+                            },
+                        },
+                        uncheckedValue: false,
+                        value: true,
+                    },
                     {
                         fieldLabel: gettext('Schedule'),
                         xtype: 'pbsCalendarEvent',
                         name: 'schedule',
-                        emptyText: gettext('none (disabled)'),
+                        allowBlank: false,
                         cbind: {
-                            deleteEmpty: '{!isCreate}',
                             value: '{scheduleValue}',
                         },
                     },
diff --git a/www/window/GCJobEdit.js b/www/window/GCJobEdit.js
index 6afcf7de1..094bed874 100644
--- a/www/window/GCJobEdit.js
+++ b/www/window/GCJobEdit.js
@@ -19,10 +19,52 @@ Ext.define('PBS.window.GCJobEdit', {
         return {};
     },
 
-    items: {
-        xtype: 'pbsCalendarEvent',
-        name: 'gc-schedule',
-        fieldLabel: gettext('GC Schedule'),
-        emptyText: gettext('none (disabled)'),
+    setValues: function (values) {
+        let me = this;
+        if (!values['gc-schedule'] || values['gc-schedule'] === '') {
+            values['gc-disable'] = true;
+        }
+
+        values['gc-enable'] = !values['gc-disable'];
+        delete values['gc-disable'];
+        me.callParent([values]);
+    },
+
+    getValues: function (dirtyOnly) {
+        let me = this;
+        let values = me.callParent([dirtyOnly]);
+
+        values['gc-disable'] = !values['gc-enable'];
+        delete values['gc-enable'];
+
+        return values;
     },
+
+    items: [
+        {
+            xtype: 'proxmoxcheckbox',
+            fieldLabel: gettext('Enable'),
+            name: 'gc-enable',
+            autoEl: {
+                tag: 'div',
+                'data-qtip': gettext('Enable scheduled execution of this task.'),
+            },
+            listeners: {
+                change: function (field, enabled) {
+                    let me = this;
+                    let view = me.up('pbsGCJobEdit');
+                    let schedule = view.down('field[name=gc-schedule]');
+                    schedule.setDisabled(!enabled);
+                },
+            },
+            uncheckedValue: false,
+            value: true,
+        },
+        {
+            xtype: 'pbsCalendarEvent',
+            name: 'gc-schedule',
+            fieldLabel: gettext('GC Schedule'),
+            allowBlank: false,
+        },
+    ],
 });
diff --git a/www/window/SyncJobEdit.js b/www/window/SyncJobEdit.js
index 961ce2951..42f6070f1 100644
--- a/www/window/SyncJobEdit.js
+++ b/www/window/SyncJobEdit.js
@@ -97,6 +97,10 @@ Ext.define('PBS.window.SyncJobEdit', {
         } else {
             values.location = 'remote';
         }
+
+        if (!values.schedule || values.schedule === '') {
+            values.disable = true;
+        }
         me.callParent([values]);
     },
 
@@ -130,6 +134,16 @@ Ext.define('PBS.window.SyncJobEdit', {
                         PBS.Utils.delete_if_default(values, 'rate-out');
                         PBS.Utils.delete_if_default(values, 'remote');
                     }
+                    values.disable = !values.enable;
+                    delete values.enable;
+
+                    return values;
+                },
+                onSetValues: function (values) {
+                    let _me = this;
+                    values.enable = !values.disable;
+                    delete values.disable;
+
                     return values;
                 },
                 cbind: {
@@ -203,13 +217,31 @@ Ext.define('PBS.window.SyncJobEdit', {
                             deleteEmpty: '{!isCreate}',
                         },
                     },
+                    {
+                        xtype: 'proxmoxcheckbox',
+                        fieldLabel: gettext('Enable'),
+                        name: 'enable',
+                        autoEl: {
+                            tag: 'div',
+                            'data-qtip': gettext('Enable scheduled execution of this task.'),
+                        },
+                        listeners: {
+                            change: function (field, enabled) {
+                                let me = this;
+                                let view = me.up('pbsSyncJobEdit');
+                                let schedule = view.down('field[name=schedule]');
+                                schedule.setDisabled(!enabled);
+                            },
+                        },
+                        uncheckedValue: false,
+                        value: true,
+                    },
                     {
                         xtype: 'pbsCalendarEvent',
                         name: 'schedule',
                         fieldLabel: gettext('Sync Schedule'),
-                        emptyText: gettext('none'),
+                        allowBlank: false,
                         cbind: {
-                            deleteEmpty: '{!isCreate}',
                             value: '{scheduleValue}',
                         },
                     },
diff --git a/www/window/VerifyJobEdit.js b/www/window/VerifyJobEdit.js
index b8d8b5810..b4eda822f 100644
--- a/www/window/VerifyJobEdit.js
+++ b/www/window/VerifyJobEdit.js
@@ -80,6 +80,14 @@ Ext.define('PBS.window.VerifyJobEdit', {
         },
     },
 
+    setValues: function (values) {
+        let me = this;
+        if (!values.schedule || values.schedule === '') {
+            values.disable = true;
+        }
+        me.callParent([values]);
+    },
+
     items: {
         xtype: 'inputpanel',
         onGetValues: function (values) {
@@ -88,6 +96,16 @@ Ext.define('PBS.window.VerifyJobEdit', {
             if (!values.id && me.up('pbsVerifyJobEdit').isCreate) {
                 values.id = 'v-' + Ext.data.identifier.Uuid.Global.generate().slice(0, 13);
             }
+            values.disable = !values.enable;
+            delete values.enable;
+
+            return values;
+        },
+        onSetValues: function (values) {
+            let _me = this;
+            values.enable = !values.disable;
+            delete values.disable;
+
             return values;
         },
         column1: [
@@ -124,14 +142,32 @@ Ext.define('PBS.window.VerifyJobEdit', {
         ],
 
         column2: [
+            {
+                xtype: 'proxmoxcheckbox',
+                fieldLabel: gettext('Enable'),
+                name: 'enable',
+                autoEl: {
+                tag: 'div',
+                    'data-qtip': gettext('Enable scheduled execution of this task.'),
+                },
+                listeners: {
+                    change: function (field, enabled) {
+                        let me = this;
+                        let view = me.up('pbsVerifyJobEdit');
+                        let schedule = view.down('field[name=schedule]');
+                        schedule.setDisabled(!enabled);
+                    },
+                },
+                uncheckedValue: false,
+                value: true,
+            },
             {
                 xtype: 'pbsCalendarEvent',
                 name: 'schedule',
                 fieldLabel: gettext('Schedule'),
-                emptyText: gettext('none (disabled)'),
+                allowBlank: false,
                 cbind: {
                     value: '{scheduleValue}',
-                    deleteEmpty: '{!isCreate}',
                 },
             },
             {
-- 
2.47.3





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

* [PATCH proxmox-backup v3 07/10] ui: improve visibility of disabled {sync,verify,tape,GC,prune} jobs on the overview page
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
                   ` (2 preceding siblings ...)
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 06/10] fix #7904: ui: job edit: introduce "Enable" checkbox " Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 08/10] ui: calendar-event: remove clear button from calendar selector Jonas Theisen
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

This commit adds additional logic to prominently display if
a job was disabled on the respective overview page by introducing
a new renderer.

If the job is disabled the text "Disabled" is shown instead of
the schedule which is still present in the config file.

For backwords compatibility if no schedule is defined the fallback
is still None.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/Utils.js             | 10 ++++++++++
 www/config/GCView.js     |  4 +++-
 www/config/PruneView.js  |  1 +
 www/config/SyncView.js   |  2 ++
 www/config/VerifyView.js |  2 ++
 www/tape/BackupJobs.js   |  2 ++
 6 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/www/Utils.js b/www/Utils.js
index d6bfd459e..1d70e8d2a 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -335,6 +335,16 @@ Ext.define('PBS.Utils', {
         );
     },
 
+    render_schedule: function (val, metadat, record) {
+        if(record.data.disable === true) {
+            return gettext('Disabled');
+        }
+        if(val) {
+            return val;
+        }
+        return Proxmox.Utils.NoneText;
+    },
+
     get_help_tool: function (blockid) {
         let info = Proxmox.Utils.get_help_info(blockid);
         if (info === undefined) {
diff --git a/www/config/GCView.js b/www/config/GCView.js
index 9fcc22344..b966fdf66 100644
--- a/www/config/GCView.js
+++ b/www/config/GCView.js
@@ -5,6 +5,7 @@ Ext.define('pbs-gc-jobs-status', {
         'upid',
         'removed-bytes',
         'pending-bytes',
+        'disable',
         'schedule',
         'next-run',
         'last-run-endtime',
@@ -73,6 +74,7 @@ Ext.define('PBS.config.GCJobView', {
                 datastore: data.store,
                 id: data.store,
                 schedule: data.schedule,
+                disable: data.disable,
                 listeners: {
                     destroy: () => this.reload(),
                 },
@@ -181,7 +183,7 @@ Ext.define('PBS.config.GCJobView', {
             header: gettext('Schedule'),
             dataIndex: 'schedule',
             hideable: false,
-            renderer: (value) => (value ? value : Proxmox.Utils.NoneText),
+            renderer: PBS.Utils.render_schedule,
             minWidth: 85,
             flex: 1,
         },
diff --git a/www/config/PruneView.js b/www/config/PruneView.js
index f38724687..c6fb750c7 100644
--- a/www/config/PruneView.js
+++ b/www/config/PruneView.js
@@ -234,6 +234,7 @@ Ext.define('PBS.config.PruneJobView', {
             minWidth: 80,
             flex: 1,
             sortable: true,
+            renderer: PBS.Utils.render_schedule,
         },
         {
             text: gettext('Keep'),
diff --git a/www/config/SyncView.js b/www/config/SyncView.js
index 386489120..499c5f2e2 100644
--- a/www/config/SyncView.js
+++ b/www/config/SyncView.js
@@ -8,6 +8,7 @@ Ext.define('pbs-sync-jobs-status', {
         'remote-ns',
         'store',
         'ns',
+        'disable',
         'schedule',
         'group-filter',
         'next-run',
@@ -395,6 +396,7 @@ Ext.define('PBS.config.SyncJobView', {
             minWidth: 80,
             flex: 1,
             sortable: true,
+            renderer: PBS.Utils.render_schedule,
         },
         {
             header: gettext('Last Sync'),
diff --git a/www/config/VerifyView.js b/www/config/VerifyView.js
index 2c63f0d79..7b72e7a35 100644
--- a/www/config/VerifyView.js
+++ b/www/config/VerifyView.js
@@ -5,6 +5,7 @@ Ext.define('pbs-verify-jobs-status', {
         'store',
         'outdated-after',
         'ignore-verified',
+        'disable',
         'schedule',
         'next-run',
         'last-run-upid',
@@ -253,6 +254,7 @@ Ext.define('PBS.config.VerifyJobView', {
             maxWidth: 220,
             minWidth: 80,
             flex: 1,
+            renderer: PBS.Utils.render_schedule,
         },
         {
             header: gettext('Last Verification'),
diff --git a/www/tape/BackupJobs.js b/www/tape/BackupJobs.js
index 68d808af5..7e36ad4d2 100644
--- a/www/tape/BackupJobs.js
+++ b/www/tape/BackupJobs.js
@@ -7,6 +7,7 @@ Ext.define('pbs-tape-backup-job-status', {
         'drive',
         'store',
         'schedule',
+        'disable',
         'comment',
         'group-filter',
         { name: 'eject-media', type: 'boolean' },
@@ -259,6 +260,7 @@ Ext.define('PBS.config.TapeBackupJobView', {
             minWidth: 80,
             flex: 1,
             sortable: true,
+            renderer: PBS.Utils.render_schedule,
         },
         {
             header: gettext('Last Backup'),
-- 
2.47.3





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

* [PATCH proxmox-backup v3 08/10] ui: calendar-event: remove clear button from calendar selector
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
                   ` (3 preceding siblings ...)
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 07/10] ui: improve visibility of disabled {sync,verify,tape,GC,prune} jobs on the overview page Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 09/10] api: create datastore: allow creation without prune job Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 10/10] ui: create datastore: add enable checkboxes for {GC, prune} Jonas Theisen
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

Since the schedule fields in all the forms do not allow
empty inputs anymore it would be unintuitive to have a clear button.

This patch removes the trigger and listener logic for that.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/form/CalendarEvent.js | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/www/form/CalendarEvent.js b/www/form/CalendarEvent.js
index b050da694..d6cc6e0e9 100644
--- a/www/form/CalendarEvent.js
+++ b/www/form/CalendarEvent.js
@@ -53,25 +53,6 @@ Ext.define('PBS.form.CalendarEvent', {
         return data;
     },
 
-    triggers: {
-        clear: {
-            cls: 'pmx-clear-trigger',
-            weight: -1,
-            hidden: true,
-            handler: function () {
-                this.triggers.clear.setVisible(false);
-                this.setValue('');
-            },
-        },
-    },
-
-    listeners: {
-        change: function (field, value) {
-            let canClear = (value ?? '') !== '';
-            field.triggers.clear.setVisible(canClear);
-        },
-    },
-
     store: {
         type: 'calendarEventExamples',
     },
-- 
2.47.3





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

* [PATCH proxmox-backup v3 09/10] api: create datastore: allow creation without prune job
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
                   ` (4 preceding siblings ...)
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 08/10] ui: calendar-event: remove clear button from calendar selector Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 10/10] ui: create datastore: add enable checkboxes for {GC, prune} Jonas Theisen
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

To allow users to create datastores without a prune job this patch
adds an optional flag to the API call.

If it is set no prune job will be generated.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 src/api2/config/datastore.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index f3644149e..76988f592 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -262,6 +262,12 @@ pub(crate) fn do_create_datastore(
                 default: false,
                 description: "Overwrite in use marker (S3 backed datastores only)."
             },
+            "prune-disable": {
+                type: Boolean,
+                optional: true,
+                default: false,
+                description: "Do not create a prune job for the new datastore."
+            },
         },
     },
     access: {
@@ -274,6 +280,7 @@ pub fn create_datastore(
     config: DataStoreConfig,
     reuse_datastore: bool,
     overwrite_in_use: bool,
+    prune_disable: bool,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<String, Error> {
     let lock = pbs_config::datastore::lock_config()?;
@@ -311,7 +318,7 @@ pub fn create_datastore(
     }
 
     let mut prune_job_config = None;
-    if config.keep.keeps_something() || !has_prune_job(&config.name)? {
+    if !prune_disable && (config.keep.keeps_something() || !has_prune_job(&config.name)?) {
         prune_job_config = config.prune_schedule.as_ref().map(|schedule| {
             let mut id = format!("default-{}-{}", config.name, Uuid::generate());
             id.truncate(32);
-- 
2.47.3





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

* [PATCH proxmox-backup v3 10/10] ui: create datastore: add enable checkboxes for {GC, prune}
  2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
                   ` (5 preceding siblings ...)
  2026-10-09 14:54 ` [PATCH proxmox-backup v3 09/10] api: create datastore: allow creation without prune job Jonas Theisen
@ 2026-10-09 14:54 ` Jonas Theisen
  6 siblings, 0 replies; 9+ messages in thread
From: Jonas Theisen @ 2026-10-09 14:54 UTC (permalink / raw)
  To: pbs-devel

To allow users to disable GC and prune jobs at creation of
a datastore without setting the schedule to none, this patch
adds the necessary checkboxes and logic.

This patch depends on a changed API endpoint to allow
a creation of the datastore without the prune job.

Signed-off-by: Jonas Theisen <j.theisen@proxmox.com>
---
 www/window/DataStoreEdit.js | 77 +++++++++++++++++++++++++++++++++++--
 1 file changed, 73 insertions(+), 4 deletions(-)

diff --git a/www/window/DataStoreEdit.js b/www/window/DataStoreEdit.js
index 911bf47d6..2a59d33ed 100644
--- a/www/window/DataStoreEdit.js
+++ b/www/window/DataStoreEdit.js
@@ -26,6 +26,19 @@ Ext.define('PBS.DataStoreEdit', {
         return {};
     },
 
+    setValues: function (values) {
+        let me = this;
+
+        if (!values['gc-schedule'] || values['gc-schedule'] === '') {
+            values['gc-disable'] = true;
+        }
+        if (!values['prune-schedule'] || values['prune-schedule'] === '') {
+            values['prune-disable'] = true;
+        }
+
+        me.callParent([values]);
+    },
+
     items: {
         xtype: 'tabpanel',
         bodyPadding: 10,
@@ -142,24 +155,62 @@ Ext.define('PBS.DataStoreEdit', {
                     },
                 ],
                 column2: [
+                    {
+                        xtype: 'proxmoxcheckbox',
+                        fieldLabel: gettext('Enable GC'),
+                        name: 'gc-enable',
+                        autoEl: {
+                            tag: 'div',
+                            'data-qtip': gettext('Enable scheduled execution of garbage collection.'),
+                        },
+                        listeners: {
+                            change: function (field, enabled) {
+                                let me = this;
+                                let view = me.up('pbsDataStoreEdit');
+                                let schedule = view.down('field[name=gc-schedule]');
+                                schedule.setDisabled(!enabled);
+                            },
+                        },
+                        uncheckedValue: false,
+                        value: true,
+                    },
                     {
                         xtype: 'pbsCalendarEvent',
                         name: 'gc-schedule',
                         fieldLabel: gettext('GC Schedule'),
-                        emptyText: gettext('none'),
+                        allowBlank: false,
                         cbind: {
-                            deleteEmpty: '{!isCreate}',
                             value: '{scheduleValue}',
                         },
                     },
+                    {
+                        xtype: 'proxmoxcheckbox',
+                        fieldLabel: gettext('Enable Prune'),
+                        name: 'prune-enable',
+                        autoEl: {
+                            tag: 'div',
+                            'data-qtip': gettext('Create a prune job for this datastore.'),
+                        },
+                        listeners: {
+                            change: function (field, enabled) {
+                                let me = this;
+                                let view = me.up('pbsDataStoreEdit');
+                                let schedule = view.down('field[name=prune-schedule]');
+                                let pruneOptions = view.down('pbsPruneInputPanel');
+                                schedule.setDisabled(!enabled);
+                                pruneOptions.setDisabled(!enabled);
+                            },
+                        },
+                        uncheckedValue: false,
+                        value: true,
+                    },
                     {
                         xtype: 'pbsCalendarEvent',
                         name: 'prune-schedule',
                         fieldLabel: gettext('Prune Schedule'),
                         value: 'daily',
-                        emptyText: gettext('none'),
+                        allowBlank: false,
                         cbind: {
-                            deleteEmpty: '{!isCreate}',
                             value: '{scheduleValue}',
                         },
                     },
@@ -238,6 +289,24 @@ Ext.define('PBS.DataStoreEdit', {
                     delete values.s3client;
                     delete values.bucket;
 
+                    values['gc-disable'] = !values['gc-enable'];
+                    if (me.isCreate) {
+                        values['prune-disable'] = !values['prune-enable'];
+                    }
+                    delete values['gc-enable'];
+                    delete values['prune-enable'];
+
+                    return values;
+                },
+
+                onSetValues: function (values) {
+                    let _me = this;
+
+                    values['gc-enable'] = !values['gc-disable'];
+                    values['prune-enable'] = !values['prune-disable'];
+                    delete values['gc-disable'];
+                    delete values['prune-disable'];
+
                     return values;
                 },
             },
-- 
2.47.3





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

end of thread, other threads:[~2026-10-09 14:55 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 14:54 [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 04/10] api: prune job: align prune job schedule to other jobs Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 05/10] fix #7904: api: implement "disable" for {sync,verify,tape,GC} jobs Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 06/10] fix #7904: ui: job edit: introduce "Enable" checkbox " Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 07/10] ui: improve visibility of disabled {sync,verify,tape,GC,prune} jobs on the overview page Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 08/10] ui: calendar-event: remove clear button from calendar selector Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 09/10] api: create datastore: allow creation without prune job Jonas Theisen
2026-10-09 14:54 ` [PATCH proxmox-backup v3 10/10] ui: create datastore: add enable checkboxes for {GC, prune} Jonas Theisen
  -- strict thread matches above, loose matches on Subject: below --
2026-10-09 14:53 [PATCH proxmox{,-backup} v3 00/10] fix #7904: Implement Enable checkboxes for all jobs Jonas Theisen
2026-10-09 14:53 ` [PATCH proxmox-backup v3 03/10] ui: prune job: align prune edit window to other "Enable" checkboxes Jonas Theisen

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.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal