From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 74A191FF0B0 for ; Fri, 09 Oct 2026 16:55:04 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id CCF5C21652; Fri, 09 Oct 2026 16:55:03 +0200 (CEST) From: Jonas Theisen To: pbs-devel@lists.proxmox.com Subject: [PATCH proxmox-backup v3 06/10] fix #7904: ui: job edit: introduce "Enable" checkbox for {sync,verify,tape,GC} jobs Date: Fri, 9 Oct 2026 16:54:37 +0200 Message-ID: <20261009145445.282494-4-j.theisen@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261009145445.282494-1-j.theisen@proxmox.com> References: <20261009145445.282494-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: 1791557696747 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.161 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: Z3MGLJ2M6E2C5Q7XEGP3NXVAIBO4YI5F X-Message-ID-Hash: Z3MGLJ2M6E2C5Q7XEGP3NXVAIBO4YI5F 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 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 --- 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