From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 1DD0A1FF0DD for ; Thu, 22 Oct 2026 18:44:33 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 8DE11216AF; Thu, 22 Oct 2026 18:44:28 +0200 (CEST) From: Jonas Theisen To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v4 7/9] fix #7904: ui: add "Enable" checkbox to {sync,verify,tape,GC} job edit Date: Thu, 22 Oct 2026 18:43:22 +0200 Message-ID: <20261022164343.353831-8-j.theisen@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261022164343.353831-1-j.theisen@proxmox.com> References: <20261022164343.353831-1-j.theisen@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792687455241 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.114 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 5BGRTEVCPG3FVLRHYBH3NL3IEDNUN6A7 X-Message-ID-Hash: 5BGRTEVCPG3FVLRHYBH3NL3IEDNUN6A7 X-MailFrom: j.theisen@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This allows users to disable jobs from the UI using the "disable" API parameter. 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 --- www/tape/window/TapeBackupJob.js | 43 ++++++++++++++++++++++-- www/window/GCJobEdit.js | 56 +++++++++++++++++++++++++++++--- www/window/SyncJobEdit.js | 39 ++++++++++++++++++++-- www/window/VerifyJobEdit.js | 38 ++++++++++++++++++++-- 4 files changed, 165 insertions(+), 11 deletions(-) diff --git a/www/tape/window/TapeBackupJob.js b/www/tape/window/TapeBackupJob.js index ad03b6076..23ba4bd80 100644 --- a/www/tape/window/TapeBackupJob.js +++ b/www/tape/window/TapeBackupJob.js @@ -46,6 +46,20 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', { }, }, + viewModel: { + data: { + jobEnabled: true, + }, + }, + + setValues: function (values) { + let me = this; + if (!values.schedule) { + values.disable = true; + } + me.callParent([values]); + }, + items: { xtype: 'tabpanel', bodyPadding: 10, @@ -66,6 +80,15 @@ Ext.define('PBS.TapeManagement.BackupJobEdit', { delete values.delete; } + values.disable = !values.enable; + delete values.enable; + + return values; + }, + onSetValues: function (values) { + values.enable = !values.disable; + delete values.disable; + return values; }, cbind: { @@ -112,15 +135,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 job.'), + }, + bind: { + value: '{jobEnabled}', + }, + uncheckedValue: false, + value: true, + }, { fieldLabel: gettext('Schedule'), xtype: 'pbsCalendarEvent', name: 'schedule', - emptyText: gettext('none (disabled)'), + allowBlank: false, cbind: { - deleteEmpty: '{!isCreate}', value: '{scheduleValue}', }, + bind: { + disabled: '{!jobEnabled}', + }, }, { fieldLabel: gettext('Export Media-Set'), diff --git a/www/window/GCJobEdit.js b/www/window/GCJobEdit.js index 6afcf7de1..c9d7d6bf3 100644 --- a/www/window/GCJobEdit.js +++ b/www/window/GCJobEdit.js @@ -19,10 +19,56 @@ Ext.define('PBS.window.GCJobEdit', { return {}; }, - items: { - xtype: 'pbsCalendarEvent', - name: 'gc-schedule', - fieldLabel: gettext('GC Schedule'), - emptyText: gettext('none (disabled)'), + viewModel: { + data: { + gcEnabled: true, + }, }, + + setValues: function (values) { + let me = this; + if (!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 job.'), + }, + bind: { + value: '{gcEnabled}', + }, + uncheckedValue: false, + value: true, + }, + { + xtype: 'pbsCalendarEvent', + name: 'gc-schedule', + fieldLabel: gettext('GC Schedule'), + allowBlank: false, + bind: { + disabled: '{!gcEnabled}', + }, + }, + ], }); diff --git a/www/window/SyncJobEdit.js b/www/window/SyncJobEdit.js index 961ce2951..e5075b3ab 100644 --- a/www/window/SyncJobEdit.js +++ b/www/window/SyncJobEdit.js @@ -90,6 +90,12 @@ Ext.define('PBS.window.SyncJobEdit', { }, }, + viewModel: { + data: { + jobEnabled: true, + }, + }, + setValues: function (values) { let me = this; if (values.id && !values.remote) { @@ -97,6 +103,10 @@ Ext.define('PBS.window.SyncJobEdit', { } else { values.location = 'remote'; } + + if (!values.schedule) { + values.disable = true; + } me.callParent([values]); }, @@ -130,6 +140,15 @@ 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) { + values.enable = !values.disable; + delete values.disable; + return values; }, cbind: { @@ -203,15 +222,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 job.'), + }, + bind: { + value: '{jobEnabled}', + }, + uncheckedValue: false, + value: true, + }, { xtype: 'pbsCalendarEvent', name: 'schedule', fieldLabel: gettext('Sync Schedule'), - emptyText: gettext('none'), + allowBlank: false, cbind: { - deleteEmpty: '{!isCreate}', value: '{scheduleValue}', }, + bind: { + disabled: '{!jobEnabled}', + }, }, { xtype: 'pmxBandwidthField', diff --git a/www/window/VerifyJobEdit.js b/www/window/VerifyJobEdit.js index b8d8b5810..21ea064a7 100644 --- a/www/window/VerifyJobEdit.js +++ b/www/window/VerifyJobEdit.js @@ -34,6 +34,7 @@ Ext.define('PBS.window.VerifyJobEdit', { ignoreVerified: true, defaultReadThreads: null, defaultVerifyThreads: null, + jobEnabled: true, }, }, @@ -80,6 +81,14 @@ Ext.define('PBS.window.VerifyJobEdit', { }, }, + setValues: function (values) { + let me = this; + if (!values.schedule) { + values.disable = true; + } + me.callParent([values]); + }, + items: { xtype: 'inputpanel', onGetValues: function (values) { @@ -88,6 +97,15 @@ 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) { + values.enable = !values.disable; + delete values.disable; + return values; }, column1: [ @@ -124,14 +142,30 @@ Ext.define('PBS.window.VerifyJobEdit', { ], column2: [ + { + xtype: 'proxmoxcheckbox', + fieldLabel: gettext('Enable'), + name: 'enable', + autoEl: { + tag: 'div', + 'data-qtip': gettext('Enable scheduled execution of this job.'), + }, + bind: { + value: '{jobEnabled}', + }, + uncheckedValue: false, + value: true, + }, { xtype: 'pbsCalendarEvent', name: 'schedule', fieldLabel: gettext('Schedule'), - emptyText: gettext('none (disabled)'), + allowBlank: false, cbind: { value: '{scheduleValue}', - deleteEmpty: '{!isCreate}', + }, + bind: { + disabled: '{!jobEnabled}', }, }, { -- 2.47.3