[pve-devel] [PATCH manager 3/3] gui: dc/backup: add new backup detail view
Aaron Lauterer
a.lauterer at proxmox.com
Thu Jan 16 14:00:36 CET 2020
The new detail view for backups shows the settings of the backup similar
to the edit dialog but read only. Additionally it does show a list of
all included guests with their disks and if the disks are included in
the backup.
Signed-off-by: Aaron Lauterer <a.lauterer at proxmox.com>
---
I am not too happy with the detail view so far. On the one hand as a
User I would expect to see the details of the backup job if I click the
Detail button, one the other hand it does not look too nice and takes
away a lot of space.
Maybe someone got a better idea on how to bring these two points
together.
Regarding tooltips @Thomas: I added a tooltip for the detail button but
as far as I can tell this pattern isn't used anywhere else for such
buttons. I am not sure if we want to introduce it at this point.
I kept my own code to determine the Icon in the Tree for VM, LXC and
disk. The only other place I found was the definition that is used in
the ResourceTree. Refactoring that and adding a disk icon did seem wrong
to me.
v1 -> v2:
* added backup job details above the list of guests and their disk status
* code cleanup and alleviating nit picks from Thomas
www/manager6/Utils.js | 30 ++++
www/manager6/dc/Backup.js | 307 +++++++++++++++++++++++++++++++++++++-
2 files changed, 336 insertions(+), 1 deletion(-)
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index efa8108e..ccf28a9a 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -207,6 +207,30 @@ Ext.define('PVE.Utils', { utilities: {
},
+ render_disk_backup_status: function(value, meta, record) {
+ if (typeof value == 'undefined') {
+ return "";
+ }
+
+ let iconCls = 'check-circle good';
+ let text = gettext('Yes');
+
+ if (!PVE.Parser.parseBoolean(value.toString())) {
+ iconCls = 'times-circle critical';
+
+ let reason = PVE.Utils.backup_reasons_table[record.get('reason')];
+
+ if (typeof reason == 'undefined') {
+ reason = record.get('reason');
+ }
+
+ text = gettext('No');
+ text = `${text} - ${reason}`;
+ }
+
+ return `<i class="fa fa-${iconCls}"></i> ${text}`;
+ },
+
render_backup_days_of_week: function(val) {
var dows = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
var selected = [];
@@ -268,6 +292,12 @@ Ext.define('PVE.Utils', { utilities: {
return "-";
},
+ backup_reasons_table: {
+ 'default exclude': gettext('Not included by default'),
+ 'not a volume': gettext('Not a volume'),
+ manual: gettext('Manually disabled'),
+ },
+
get_kvm_osinfo: function(value) {
var info = { base: 'Other' }; // default
if (value) {
diff --git a/www/manager6/dc/Backup.js b/www/manager6/dc/Backup.js
index f7792002..f9da66d9 100644
--- a/www/manager6/dc/Backup.js
+++ b/www/manager6/dc/Backup.js
@@ -377,6 +377,264 @@ Ext.define('PVE.dc.BackupEdit', {
});
+Ext.define('PVE.dc.BackupDiskTree', {
+ extend: 'Ext.tree.Panel',
+ alias: 'widget.pveBackupDiskTree',
+
+ folderSort: true,
+ rootVisible: false,
+
+ store: {
+ sorters: 'id',
+ data: {},
+ },
+
+ tools: [
+ {
+ type: 'expand',
+ tooltip: gettext('Expand All'),
+ scope: this,
+ callback: function(panel) {
+ panel.expandAll();
+ },
+ },
+ {
+ type: 'collapse',
+ tooltip: gettext('Collapse All'),
+ scope: this,
+ callback: function(panel) {
+ panel.collapseAll();
+ }
+ },
+ ],
+
+ columns: [
+ {
+ xtype: 'treecolumn',
+ text: gettext('Guest Image'),
+ dataIndex: 'id',
+ flex: 6,
+ },
+ {
+ text: gettext('Type'),
+ dataIndex: 'type',
+ flex: 1,
+ },
+ {
+ text: gettext('Backup Job'),
+ renderer: PVE.Utils.render_disk_backup_status,
+ dataIndex: 'status',
+ flex: 3,
+ },
+ ],
+
+ reload: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+
+ Proxmox.Utils.API2Request({
+ url: "/cluster/backup/" + me.jobid + "/included_disks",
+ waitMsgTarget: me,
+ method: 'GET',
+ failure: function(response, opts) {
+ Proxmox.Utils.setErrorMask(me, response.htmlStatus);
+ },
+ success: function(response, opts) {
+ sm.deselectAll();
+ me.setRootNode(response.result.data);
+ me.expandAll();
+ },
+ });
+ },
+
+ initComponent: function() {
+ var me = this;
+
+ if (!me.jobid) {
+ throw "no job id specified";
+ }
+
+ var sm = Ext.create('Ext.selection.TreeModel', {});
+
+ Ext.apply(me, {
+ selModel: sm,
+ fields: ['id', 'type',
+ {
+ type: 'string',
+ name: 'iconCls',
+ calculate: function(data) {
+ var txt = 'fa x-fa-tree fa-';
+ if (data.leaf) {
+ return txt + 'hdd-o';
+ } else if (data.type === 'VM') {
+ return txt + 'desktop';
+ } else if (data.type === 'CT') {
+ return txt + 'cube';
+ }
+ }
+ }
+ ],
+ });
+
+ me.callParent();
+
+ me.reload();
+ }
+});
+
+Ext.define('PVE.dc.BackupInfo', {
+ extend: 'Proxmox.panel.InputPanel',
+ alias: 'widget.pveBackupInfo',
+
+ padding: 10,
+
+ column1: [
+ {
+ name: 'node',
+ fieldLabel: gettext('Node'),
+ xtype: 'displayfield',
+ renderer: function (value) {
+ if (!value) {
+ return '-- ' + gettext('All') + ' --';
+ } else {
+ return value;
+ }
+ },
+ },
+ {
+ name: 'storage',
+ fieldLabel: gettext('Storage'),
+ xtype: 'displayfield',
+ },
+ {
+ name: 'dow',
+ fieldLabel: gettext('Day of week'),
+ xtype: 'displayfield',
+ renderer: PVE.Utils.render_backup_days_of_week,
+ },
+ {
+ name: 'starttime',
+ fieldLabel: gettext('Start Time'),
+ xtype: 'displayfield',
+ },
+ {
+ name: 'selMode',
+ fieldLabel: gettext('Selection mode'),
+ xtype: 'displayfield',
+ },
+ {
+ name: 'pool',
+ fieldLabel: gettext('Pool to backup'),
+ xtype: 'displayfield',
+ }
+ ],
+ column2: [
+ {
+ name: 'mailto',
+ fieldLabel: gettext('Send email to'),
+ xtype: 'displayfield',
+ },
+ {
+ name: 'mailnotification',
+ fieldLabel: gettext('Email notification'),
+ xtype: 'displayfield',
+ renderer: function (value) {
+ let msg;
+ switch (value) {
+ case 'always':
+ msg = gettext('Always');
+ break;
+ case 'failure':
+ msg = gettext('On failure only');
+ break;
+ }
+ return msg;
+ },
+ },
+ {
+ name: 'compress',
+ fieldLabel: gettext('Compression'),
+ xtype: 'displayfield',
+ },
+ {
+ name: 'mode',
+ fieldLabel: gettext('Mode'),
+ xtype: 'displayfield',
+ renderer: function (value) {
+ let msg;
+ switch (value) {
+ case 'snapshot':
+ msg = gettext('Snapshot');
+ break;
+ case 'suspend':
+ msg = gettext('Suspend');
+ break;
+ case 'stop':
+ msg = gettext('Stop');
+ break;
+ }
+ return msg;
+ },
+ },
+ {
+ name: 'enabled',
+ fieldLabel: gettext('Enabled'),
+ xtype: 'displayfield',
+ renderer: function (value) {
+ if (PVE.Parser.parseBoolean(value.toString())) {
+ return gettext('Yes');
+ } else {
+ return gettext('No');
+ }
+ },
+ },
+ ],
+
+ setValues: function(values) {
+ var me = this;
+
+ Ext.iterate(values, function(fieldId, val) {
+ let field = me.query('[isFormField][name=' + fieldId + ']')[0];
+ if (field) {
+ field.setValue(val);
+ }
+ });
+
+ // selection Mode depends on the presence/absence of several keys
+ let selModeField = me.query('[isFormField][name=selMode]')[0];
+ let selMode = 'none';
+ if (values.exclude) {
+ selMode = gettext('Exclude selected VMs');
+ }
+ if (values.vmid) {
+ selMode = gettext('Include selected VMs');
+ }
+ if (values.all) {
+ selMode = gettext('All');
+ }
+ if (values.pool) {
+ selMode = gettext('Pool based');
+ }
+ selModeField.setValue(selMode);
+
+ if (!values.pool) {
+ let poolField = me.query('[isFormField][name=pool]')[0];
+ poolField.setVisible(0);
+ }
+ },
+
+ initComponent: function() {
+ var me = this;
+
+ if (!me.record) {
+ throw "no data provided";
+ }
+ me.callParent();
+
+ me.setValues(me.record);
+ }
+});
+
Ext.define('PVE.dc.BackupView', {
extend: 'Ext.grid.GridPanel',
@@ -416,6 +674,43 @@ Ext.define('PVE.dc.BackupView', {
win.show();
};
+ var run_detail = function() {
+ let rec = sm.getSelection()[0]
+ if (!rec) {
+ return;
+ }
+ var me = this;
+ var infoview = Ext.create('PVE.dc.BackupInfo', {
+ flex: 0,
+ layout: 'fit',
+ record: rec.data,
+ });
+ var disktree = Ext.create('PVE.dc.BackupDiskTree', {
+ title: gettext('Included disks'),
+ flex: 1,
+ jobid: rec.data.id,
+ });
+
+ var win = Ext.create('Ext.window.Window', {
+ modal: true,
+ width: 600,
+ height: 500,
+ resizable: true,
+ layout: 'fit',
+ title: gettext('Backup Details'),
+
+ items:[{
+ xtype: 'panel',
+ region: 'center',
+ layout: {
+ type: 'vbox',
+ align: 'stretch'
+ },
+ items: [infoview, disktree],
+ }]
+ }).show();
+ };
+
var run_backup_now = function(job) {
job = Ext.clone(job);
@@ -516,6 +811,14 @@ Ext.define('PVE.dc.BackupView', {
}
});
+ var detail_btn = new Proxmox.button.Button({
+ text: gettext('Detail'),
+ disabled: true,
+ tooltip: gettext('Show job details and which guests and volumes are affected by the backup job'),
+ selModel: sm,
+ handler: run_detail,
+ });
+
Proxmox.Utils.monStoreErrors(me, store);
Ext.apply(me, {
@@ -539,7 +842,9 @@ Ext.define('PVE.dc.BackupView', {
remove_btn,
edit_btn,
'-',
- run_btn
+ run_btn,
+ '-',
+ detail_btn,
],
columns: [
{
--
2.20.1
More information about the pve-devel
mailing list