[pve-devel] [PATCH manager v2 5/5] fix #2609 gui: backup: add summary window

Aaron Lauterer a.lauterer at proxmox.com
Thu May 7 13:57:29 CEST 2020


Adds a new `Summary` button to the backup panel which opens a new
window containing a searchable view of all guests and whether they are
backed up by any job or not.

Signed-off-by: Aaron Lauterer <a.lauterer at proxmox.com>
---

I took the code for the search field from the ResourceGrid, simplified
it and adapted it more to having it statically defined and not all in
the initComponent method.

v1->v2:
* renamed ostore to cold_store
* changed double negative for permissions `not_all_permissions` to
  `permissions_for_all`

 www/manager6/dc/Backup.js | 200 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 200 insertions(+)

diff --git a/www/manager6/dc/Backup.js b/www/manager6/dc/Backup.js
index d4ecf4a8..067c1d13 100644
--- a/www/manager6/dc/Backup.js
+++ b/www/manager6/dc/Backup.js
@@ -679,6 +679,171 @@ Ext.define('PVE.dc.BackupInfo', {
     }
 });
 
+Ext.define('PVE.dc.BackedGuests', {
+    extend: 'Ext.grid.GridPanel',
+    alias: 'widget.pveBackedGuests',
+
+    cold_store: [],
+    textfilter: '',
+
+    store: {
+	sorters: 'vmid',
+	data: {},
+    },
+
+    viewModel: {
+	data: {
+	    permissionsForAll: 1,
+	},
+	formulas: {
+	    hidePermissionsHint: (get) => get('permissionsForAll'),
+	}
+    },
+
+    dockedItems: [{
+	xtype: 'toolbar',
+	dock: 'bottom',
+	userCls: 'pmx-hint',
+	items: [
+	    {
+		xtype: 'displayfield',
+		value: gettext("You don't have permission to see all guests."),
+	    },
+	],
+	bind: {
+	    hidden: '{hidePermissionsHint}',
+	},
+    }],
+
+    columns: [
+	{
+	    header: gettext('Type'),
+	    dataIndex: "type",
+	    renderer: PVE.Utils.render_resource_type,
+	    flex: 1,
+	    sortable: true,
+	},
+	{
+	    header: gettext('VMID'),
+	    dataIndex: 'vmid',
+	    flex: 1,
+	    sortable: true,
+	},
+	{
+	    header: gettext('Name'),
+	    dataIndex: 'name',
+	    flex: 2,
+	    sortable: true,
+	},
+	{
+	    header: gettext('Backup'),
+	    renderer: PVE.Utils.render_backup_status,
+	    dataIndex: "backed_up",
+	    flex: 1,
+	    sortable: true,
+	},
+    ],
+
+    reload: function() {
+	var me = this;
+	var sm = me.getSelectionModel();
+
+	Proxmox.Utils.API2Request({
+	    url: '/cluster/backupsummary/included_status',
+	    waitMsgTarget: me,
+	    method: 'GET',
+	    failure: function(response, opts) {
+		Proxmox.Utils.setErrorMask(me, response.htmlStatus);
+	    },
+	    success: function(response, opts) {
+		let viewModel = me.getViewModel();
+		viewModel.set('permissionsForAll', response.result.data['permissions_for_all']);
+
+		me.cold_store = response.result.data.guests;
+
+		me.updateGrid();
+	    },
+	});
+    },
+
+    textfilter_match: function(item) {
+	let me = this;
+	let match = false;
+	Ext.each(['name', 'vmid', 'type'], function(field) {
+	    let v = item[field].toString();
+	    if (v !== undefined) {
+		v = v.toLowerCase();
+		if (v.indexOf(me.textfilter) >= 0) {
+		    match = true;
+		    return false;
+		}
+	    }
+	});
+	return match;
+    },
+
+    updateGrid: function() {
+	let me = this;
+	me.store.suspendEvents();
+
+	if (me.textfilter) {
+	    let matched_items = [];
+
+	    Ext.each(me.cold_store, function(item) {
+		if (me.textfilter_match(item)) {
+		    matched_items.push(item);
+		}
+	    });
+	    me.store.setData(matched_items);
+	}
+	else {
+	    me.store.setData(me.cold_store);
+	}
+
+	me.store.resumeEvents();
+	me.store.fireEvent('refresh', me.store);
+    },
+
+    initComponent: function() {
+	let me = this;
+
+
+	let filter_task = new Ext.util.DelayedTask(function(){
+	    me.updateGrid();
+	});
+
+
+	Ext.apply(me, {
+	    stateful: true,
+	    stateId: 'gird-dc-backed-guests',
+	    tbar: [
+		'->',
+		gettext('Search') + ':', ' ',
+		{
+		    xtype: 'textfield',
+		    width: 200,
+		    value: me.textfilter,
+		    enableKeyEvents: true,
+		    listeners: {
+			keyup: function(field, e) {
+			    var v = field.getValue();
+			    me.textfilter = v.toLowerCase();
+			    filter_task.delay(500);
+			}
+		    }
+		}
+	    ],
+	    viewConfig: {
+		stripeRows: true,
+		trackOver: false,
+            },
+	});
+	me.callParent();
+
+	me.reload();
+    }
+});
+
 Ext.define('PVE.dc.BackupView', {
     extend: 'Ext.grid.GridPanel',
 
@@ -755,6 +920,34 @@ Ext.define('PVE.dc.BackupView', {
 	    }).show();
 	};
 
+	var run_summary = function() {
+	    var me = this;
+	    var backedinfo = Ext.create('PVE.dc.BackedGuests', {
+		title: gettext('Included in a backup'),
+		flex: 1,
+		layout: 'fit',
+	    });
+
+	    var win = Ext.create('Ext.window.Window', {
+		modal: true,
+		width: 600,
+		height: 500,
+		resizable: true,
+		layout: 'fit',
+		title: gettext('Summary'),
+
+		items:[{
+		    xtype: 'panel',
+		    region: 'center',
+		    layout: {
+			type: 'vbox',
+			align: 'stretch'
+		    },
+		    items: [backedinfo],
+		}]
+	    }).show();
+	};
+
 	var run_backup_now = function(job) {
 	    job = Ext.clone(job);
 
@@ -863,6 +1056,12 @@ Ext.define('PVE.dc.BackupView', {
 	    handler: run_detail,
 	});
 
+	var summary_btn = new Proxmox.button.Button({
+	    text: gettext('Summary'),
+	    tooltip: gettext('Show which guests are part of any backup job'),
+	    handler: run_summary,
+	});
+
 	Proxmox.Utils.monStoreErrors(me, store);
 
 	Ext.apply(me, {
@@ -889,6 +1088,7 @@ Ext.define('PVE.dc.BackupView', {
 		'-',
 		run_btn,
 		'-',
+		summary_btn,
 	    ],
 	    columns: [
 		{
-- 
2.20.1





More information about the pve-devel mailing list