[pbs-devel] [PATCH proxmox-backup v2 4/5] ui: tape/window/TapeRestore: enabling selecting multiple snapshots

Dominik Csapak d.csapak at proxmox.com
Fri May 14 14:59:22 CEST 2021


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 <d.csapak at proxmox.com>
---
 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('<br>');
-	    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






More information about the pbs-devel mailing list