From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 8FDA51FF137 for ; Tue, 17 Mar 2026 12:43:33 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C3960BA9F; Tue, 17 Mar 2026 12:43:45 +0100 (CET) Message-ID: <720f67da-1791-4b7b-8fb9-d567dd734d60@proxmox.com> Date: Tue, 17 Mar 2026 12:43:41 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH proxmox-backup v4 6/7] ui: add move group action To: Hannes Laimer , pbs-devel@lists.proxmox.com References: <20260311151315.133637-1-h.laimer@proxmox.com> <20260311151315.133637-7-h.laimer@proxmox.com> Content-Language: en-US, de-DE From: Christian Ebner In-Reply-To: <20260311151315.133637-7-h.laimer@proxmox.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1773747780883 X-SPAM-LEVEL: Spam detection results: 0 AWL -1.006 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.408 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.819 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.903 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. 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: Y22UF2HZTXSTY2XLYB7RCZFVXRU44M7O X-Message-ID-Hash: Y22UF2HZTXSTY2XLYB7RCZFVXRU44M7O X-MailFrom: c.ebner@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: One comment inline. On 3/11/26 4:13 PM, Hannes Laimer wrote: > Signed-off-by: Hannes Laimer > --- > www/Makefile | 1 + > www/datastore/Content.js | 61 ++++++++++++++++++++++++++++++++++++++++ > www/window/GroupMove.js | 56 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 118 insertions(+) > create mode 100644 www/window/GroupMove.js > > diff --git a/www/Makefile b/www/Makefile > index 9ebf0445..db775b64 100644 > --- a/www/Makefile > +++ b/www/Makefile > @@ -77,6 +77,7 @@ JSSRC= \ > window/ACLEdit.js \ > window/BackupGroupChangeOwner.js \ > window/CreateDirectory.js \ > + window/GroupMove.js \ > window/DataStoreEdit.js \ > window/NamespaceEdit.js \ > window/MaintenanceOptions.js \ > diff --git a/www/datastore/Content.js b/www/datastore/Content.js > index a2aa1949..ccd48616 100644 > --- a/www/datastore/Content.js > +++ b/www/datastore/Content.js > @@ -635,6 +635,50 @@ Ext.define('PBS.DataStoreContent', { > }); > }, > > + moveNS: function () { > + let me = this; > + let view = me.getView(); > + if (!view.namespace || view.namespace === '') { > + return; > + } > + let win = Ext.create('PBS.window.NamespaceMove', { > + datastore: view.datastore, > + namespace: view.namespace, > + taskDone: (success) => { > + if (success) { > + let newNs = win.getNewNamespace(); > + view.down('pbsNamespaceSelector').store?.load(); > + me.nsChange(null, newNs); > + } > + }, > + }); > + win.show(); > + }, > + > + moveGroup: function (data) { > + let me = this; > + let view = me.getView(); > + let group = `${data.backup_type}/${data.backup_id}`; > + Ext.create('PBS.window.GroupMove', { > + datastore: view.datastore, > + namespace: view.namespace, > + backupType: data.backup_type, > + backupId: data.backup_id, > + group, > + taskDone: () => me.reload(), > + }).show(); > + }, > + > + onMove: function (table, rI, cI, item, e, { data }) { > + let me = this; > + if (data.ty === 'group') { > + me.moveGroup(data); > + } else if (data.ty === 'ns') { > + me.moveNS(); > + } > + }, > + > + > forgetGroup: function (data) { > let me = this; > let view = me.getView(); > @@ -1080,6 +1124,23 @@ Ext.define('PBS.DataStoreContent', { > }, > isActionDisabled: (v, r, c, i, rec) => rec.data.ty !== 'dir', > }, > + { > + handler: 'onMove', > + getTip: (v, m, { data }) => { > + if (data.ty === 'group') { > + return Ext.String.format(gettext("Move group '{0}'"), v); > + } > + return Ext.String.format(gettext("Move namespace '{0}'"), v); > + }, > + getClass: (v, m, { data }) => { > + if (data.ty === 'group') { return 'fa fa-arrows'; } > + if (data.ty === 'ns' && !data.isRootNS && data.ns === undefined) { > + return 'fa fa-arrows'; > + } > + return 'pmx-hidden'; > + }, > + isActionDisabled: (v, r, c, i, { data }) => false, > + }, comment: placing this right before the prune icon is a bit dangerous (although a prune will ask for confirmation). Since the protected icons is not shown for groups and namespaces, it should rather be placed before that, right after the verification icon. Further, what I missed is having this also in the context menu opened on right click of the group/namespace. > { > handler: 'onForget', > getTip: (v, m, { data }) => { > diff --git a/www/window/GroupMove.js b/www/window/GroupMove.js > new file mode 100644 > index 00000000..f663c606 > --- /dev/null > +++ b/www/window/GroupMove.js > @@ -0,0 +1,56 @@ > +Ext.define('PBS.window.GroupMove', { > + extend: 'Proxmox.window.Edit', > + alias: 'widget.pbsGroupMove', > + mixins: ['Proxmox.Mixin.CBind'], > + > + onlineHelp: 'storage-namespaces', > + > + isCreate: true, > + submitText: gettext('Move'), > + showTaskViewer: true, > + > + cbind: { > + url: '/api2/extjs/admin/datastore/{datastore}/groups', > + title: (get) => Ext.String.format(gettext("Move Backup Group '{0}'"), get('group')), > + }, > + method: 'PUT', > + > + width: 400, > + fieldDefaults: { > + labelWidth: 120, > + }, > + > + items: { > + xtype: 'inputpanel', > + onGetValues: function (values) { > + let win = this.up('window'); > + let result = { > + 'backup-type': win.backupType, > + 'backup-id': win.backupId, > + 'new-ns': values['new-ns'] || '', > + }; > + if (win.namespace && win.namespace !== '') { > + result.ns = win.namespace; > + } > + return result; > + }, > + items: [ > + { > + xtype: 'displayfield', > + fieldLabel: gettext('Group'), > + cbind: { > + value: '{group}', > + }, > + }, > + { > + xtype: 'pbsNamespaceSelector', > + name: 'new-ns', > + fieldLabel: gettext('Target Namespace'), > + allowBlank: true, > + cbind: { > + datastore: '{datastore}', > + }, > + }, > + ], > + }, > +});