From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id CDDF7709B3 for ; Fri, 14 May 2021 14:59:57 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id C0B191760D for ; Fri, 14 May 2021 14:59:27 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 4B7DA175EA for ; Fri, 14 May 2021 14:59:25 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 253F542A2D for ; Fri, 14 May 2021 14:59:25 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Fri, 14 May 2021 14:59:22 +0200 Message-Id: <20210514125923.14955-5-d.csapak@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210514125923.14955-1-d.csapak@proxmox.com> References: <20210514125923.14955-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.016 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [values.store, content.store, data.store, node.data, entry.store, rec.data] Subject: [pbs-devel] [PATCH proxmox-backup v2 4/5] ui: tape/window/TapeRestore: enabling selecting multiple snapshots X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 May 2021 12:59:57 -0000 by including the new snapshotselector. If a whole media-set is to be restored, select all snapshots to achieve this, we drop the 'restoreid' and 'datastores' properties for the restore window, and replace them by a 'prefilter' object (with 'store' and 'snapshot' properties) to be able to show the snapshots, we now have to always load the content of that media-set, so drop the short-circuit if we have the datastores already. also to improve space-usage, shift the datastores mapping grid in the right column, and all non datastore related options in the left one, showing the snapshot grid below (the datastore mapping is now limited to 150px; ~3 datastores, and scrollable) Signed-off-by: Dominik Csapak --- www/tape/BackupOverview.js | 27 +++------- www/tape/window/TapeRestore.js | 99 ++++++++++++++++++---------------- 2 files changed, 61 insertions(+), 65 deletions(-) diff --git a/www/tape/BackupOverview.js b/www/tape/BackupOverview.js index 0e105274..eb8ef907 100644 --- a/www/tape/BackupOverview.js +++ b/www/tape/BackupOverview.js @@ -19,27 +19,13 @@ Ext.define('PBS.TapeManagement.BackupOverview', { restore: function(view, rI, cI, item, e, rec) { let me = this; - let node = rec; - let mediaset = node.data.is_media_set ? node.data.text : node.data['media-set']; - let uuid = node.data['media-set-uuid']; - - let list; - let datastores; - if (node.data.restoreid !== undefined) { - list = [node.data.restoreid]; - datastores = [node.data.store]; - } else { - datastores = node.data.datastores; - while (!datastores && node.get('depth') > 2) { - node = node.parentNode; - datastores = node.data.datastores; - } - } + let mediaset = rec.data.is_media_set ? rec.data.text : rec.data['media-set']; + let uuid = rec.data['media-set-uuid']; + let prefilter = rec.data.prefilter; Ext.create('PBS.TapeManagement.TapeRestoreWindow', { mediaset, uuid, - datastores, - list, + prefilter, listeners: { destroy: function() { me.reload(); @@ -157,7 +143,10 @@ Ext.define('PBS.TapeManagement.BackupOverview', { entry.leaf = true; entry.children = []; entry['media-set'] = media_set; - entry.restoreid = `${entry.store}:${entry.snapshot}`; + entry.prefilter = { + store: entry.store, + snapshot: entry.snapshot, + }; let iconCls = PBS.Utils.get_type_icon_cls(entry.snapshot); if (iconCls !== '') { entry.iconCls = `fa ${iconCls}`; diff --git a/www/tape/window/TapeRestore.js b/www/tape/window/TapeRestore.js index 9967d9d8..9359a030 100644 --- a/www/tape/window/TapeRestore.js +++ b/www/tape/window/TapeRestore.js @@ -13,12 +13,8 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { cbindData: function(config) { let me = this; - me.isSingle = false; - me.listText = ""; - if (me.list !== undefined) { - me.isSingle = true; - me.listText = me.list.join('
'); - me.title = gettext('Restore Snapshot'); + if (me.prefilter !== undefined) { + me.title = gettext('Restore Snapshot(s)'); } return {}; }, @@ -46,8 +42,8 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { } delete values.mapping; - if (me.up('window').list !== undefined) { - values.snapshots = me.up('window').list; + if (Ext.isString(values.snapshots)) { + values.snapshots = values.snapshots.split(','); } values.store = datastores.join(','); @@ -72,23 +68,11 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { value: '{uuid}', }, }, - { - xtype: 'displayfield', - fieldLabel: gettext('Snapshot(s)'), - submitValue: false, - cbind: { - hidden: '{!isSingle}', - value: '{listText}', - }, - }, { xtype: 'pbsDriveSelector', fieldLabel: gettext('Drive'), name: 'drive', }, - ], - - column2: [ { xtype: 'pbsUserSelector', name: 'notify-user', @@ -109,9 +93,13 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { skipEmptyText: true, renderer: Ext.String.htmlEncode, }, + ], + + column2: [ { xtype: 'pbsDataStoreSelector', fieldLabel: gettext('Target Datastore'), + labelWidth: 120, reference: 'defaultDatastore', name: 'store', listeners: { @@ -122,9 +110,6 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { }, }, }, - ], - - columnB: [ { fieldLabel: gettext('Datastore Mapping'), labelWidth: 200, @@ -140,6 +125,20 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { hidden: true, }, ], + + columnB: [ + { + xtype: 'pbsTapeSnapshotGrid', + reference: 'snapshotGrid', + name: 'snapshots', + // will be shown/enabled on successful load + disabled: true, + hidden: true, + cbind: { + prefilter: '{prefilter}', + }, + }, + ], }, ], @@ -172,29 +171,34 @@ Ext.define('PBS.TapeManagement.TapeRestoreWindow', { let me = this; me.callParent(); - if (me.datastores) { - me.setDataStores(me.datastores); - } else { - // use timeout so that the window is rendered already - // for correct masking - setTimeout(function() { - Proxmox.Utils.API2Request({ - waitMsgTarget: me, - url: `/tape/media/content?media-set=${me.uuid}`, - success: function(response, opt) { - let datastores = {}; - for (const content of response.result.data) { - datastores[content.store] = true; - } - me.setDataStores(Object.keys(datastores)); - }, - failure: function() { - // ignore failing api call, maybe catalog is missing - me.setDataStores(); - }, - }); - }, 10); - } + // use timeout so that the window is rendered already + // for correct masking + let grid = me.lookup('snapshotGrid'); + setTimeout(function() { + Proxmox.Utils.API2Request({ + waitMsgTarget: me, + url: `/tape/media/content?media-set=${me.uuid}`, + success: function(response, opt) { + let datastores = {}; + for (const content of response.result.data) { + datastores[content.store] = true; + } + me.setDataStores(Object.keys(datastores)); + if (response.result.data.length > 0) { + grid.setDisabled(false); + grid.setVisible(true); + grid.getStore().setData(response.result.data); + grid.getSelectionModel().selectAll(); + // we've shown a big list, center the window again + me.center(); + } + }, + failure: function() { + // ignore failing api call, maybe catalog is missing + me.setDataStores(); + }, + }); + }, 10); }, }); @@ -203,6 +207,9 @@ Ext.define('PBS.TapeManagement.DataStoreMappingGrid', { alias: 'widget.pbsDataStoreMappingField', mixins: ['Ext.form.field.Field'], + maxHeight: 150, + scrollable: true, + getValue: function() { let me = this; let datastores = []; -- 2.20.1