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 08F291FF0A3 for ; Thu, 01 Oct 2026 15:13:31 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 824E421739; Thu, 01 Oct 2026 15:13:15 +0200 (CEST) From: Elias Huhsovitz To: pve-devel@lists.proxmox.com Subject: [PATCH manager 1/2] ui: dc: backup edit: add filter for guests without backup job Date: Thu, 1 Oct 2026 15:13:08 +0200 Message-ID: <20261001131309.172079-2-e.huhsovitz@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261001131309.172079-1-e.huhsovitz@proxmox.com> References: <20261001131309.172079-1-e.huhsovitz@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1790860391159 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.411 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) POISEN_SPAM_PILL 0.1 Meta: its spam POISEN_SPAM_PILL_1 0.1 random spam to be learned in bayes POISEN_SPAM_PILL_3 0.1 random spam to be learned in bayes 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: VGQSAXZISXVIHDA6AXOI5EFHGUF6GNFE X-Message-ID-Hash: VGQSAXZISXVIHDA6AXOI5EFHGUF6GNFE X-MailFrom: e.huhsovitz@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 CC: Elias Huhsovitz X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add a checkbox in the guest selector toolbar that shows only guests which are not covered by any backup job. The window fetches the guest list from /cluster/backup-info/not-backed-up once and caches it for the lifetime of the edit window. Use a named node filter when the node selector changes instead of clearing all store filters. This keeps the new filter and the review filter active across node changes. Signed-off-by: Elias Huhsovitz --- www/manager6/dc/Backup.js | 70 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/www/manager6/dc/Backup.js b/www/manager6/dc/Backup.js index d3db9d9c..62f1838b 100644 --- a/www/manager6/dc/Backup.js +++ b/www/manager6/dc/Backup.js @@ -66,10 +66,14 @@ Ext.define('PVE.dc.BackupEdit', { me.resetSearch(); - store.clearFilter(); - store.filterBy(function (rec) { - return !value || rec.get('node') === value; - }); + store.removeFilter('vmgrid-node'); + if (value) { + store.addFilter({ + id: 'vmgrid-node', + property: 'node', + value: value, + }); + } if (value) { let selModel = vmgrid.getSelectionModel(); @@ -246,6 +250,45 @@ Ext.define('PVE.dc.BackupEdit', { } }, + noBackupJobFilterChange: function (checkbox, checked) { + let me = this; + let store = me.lookup('vmgrid').getStore(); + + if (!checked) { + store.removeFilter(me.noJobFilter); + return; + } + + if (me.noJobVmIds) { + store.addFilter(me.noJobFilter); + return; + } + + checkbox.setDisabled(true); + Proxmox.Utils.API2Request({ + url: '/cluster/backup-info/not-backed-up', + method: 'GET', + success: function (response) { + let noJobVmIds = {}; + let data = response.result.data || []; + for (const rec of data) { + noJobVmIds[String(rec.vmid)] = true; + } + me.noJobVmIds = noJobVmIds; + + if (checkbox.getValue()) { + store.addFilter(me.noJobFilter); + } + checkbox.setDisabled(false); + }, + failure: function (response) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + checkbox.setValue(false); + checkbox.setDisabled(false); + }, + }); + }, + init: function (view) { let me = this; @@ -254,6 +297,15 @@ Ext.define('PVE.dc.BackupEdit', { scope: me, filterFn: me.reviewFn, }); + + me.noJobFilter = new Ext.util.Filter({ + id: 'vmgrid-no-job', + scope: me, + filterFn: function (record) { + return me.noJobVmIds && me.noJobVmIds[String(record.get('vmid'))]; + }, + }); + me.lookup('searchField').setTargetStore(me.lookup('vmgrid').getStore()); if (view.isCreate) { @@ -463,6 +515,16 @@ Ext.define('PVE.dc.BackupEdit', { '->', { xtype: 'proxmoxcheckbox', + reference: 'noBackupJobCheckbox', + boxLabel: gettext('Only guests without backup job'), + submitValue: false, + listeners: { + change: 'noBackupJobFilterChange', + }, + }, + { + xtype: 'proxmoxcheckbox', + reference: 'reviewCheckbox', boxLabel: gettext('Review'), submitValue: false, listeners: { -- 2.47.3