ui: dc/Backup: eslint fixes and code cleanup/refactoring

this one would deserve much more, especially the newer backup job
detail and not-backed-up view should be split out and done in a
declarative way (view view-controller)

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2021-05-17 20:40:10 +02:00
parent 1848bf9eb0
commit 12809bba4f

View File

@ -5,13 +5,11 @@ Ext.define('PVE.dc.BackupEdit', {
defaultFocus: undefined, defaultFocus: undefined,
initComponent: function() { initComponent: function() {
var me = this; let me = this;
me.isCreate = !me.jobid; me.isCreate = !me.jobid;
var url; let url, method;
var method;
if (me.isCreate) { if (me.isCreate) {
url = '/api2/extjs/cluster/backup'; url = '/api2/extjs/cluster/backup';
method = 'POST'; method = 'POST';
@ -20,12 +18,12 @@ Ext.define('PVE.dc.BackupEdit', {
method = 'PUT'; method = 'PUT';
} }
var vmidField = Ext.create('Ext.form.field.Hidden', { let vmidField = Ext.create('Ext.form.field.Hidden', {
name: 'vmid', name: 'vmid',
}); });
// 'value' can be assigned a string or an array // 'value' can be assigned a string or an array
var selModeField = Ext.create('Proxmox.form.KVComboBox', { let selModeField = Ext.create('Proxmox.form.KVComboBox', {
xtype: 'proxmoxKVComboBox', xtype: 'proxmoxKVComboBox',
comboItems: [ comboItems: [
['include', gettext('Include selected VMs')], ['include', gettext('Include selected VMs')],
@ -38,7 +36,7 @@ Ext.define('PVE.dc.BackupEdit', {
value: '', value: '',
}); });
var sm = Ext.create('Ext.selection.CheckboxModel', { let sm = Ext.create('Ext.selection.CheckboxModel', {
mode: 'SIMPLE', mode: 'SIMPLE',
listeners: { listeners: {
selectionchange: function(model, selected) { selectionchange: function(model, selected) {
@ -56,7 +54,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var storagesel = Ext.create('PVE.form.StorageSelector', { let storagesel = Ext.create('PVE.form.StorageSelector', {
fieldLabel: gettext('Storage'), fieldLabel: gettext('Storage'),
nodename: 'localhost', nodename: 'localhost',
storageContent: 'backup', storageContent: 'backup',
@ -78,7 +76,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var store = new Ext.data.Store({ let store = new Ext.data.Store({
model: 'PVEResources', model: 'PVEResources',
sorters: { sorters: {
property: 'vmid', property: 'vmid',
@ -86,7 +84,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var vmgrid = Ext.createWidget('grid', { let vmgrid = Ext.createWidget('grid', {
store: store, store: store,
border: true, border: true,
height: 300, height: 300,
@ -125,7 +123,7 @@ Ext.define('PVE.dc.BackupEdit', {
], ],
}); });
var selectPoolMembers = function(poolid) { let selectPoolMembers = function(poolid) {
if (!poolid) { if (!poolid) {
return; return;
} }
@ -140,7 +138,7 @@ Ext.define('PVE.dc.BackupEdit', {
sm.selectAll(true); sm.selectAll(true);
}; };
var selPool = Ext.create('PVE.form.PoolSelector', { let selPool = Ext.create('PVE.form.PoolSelector', {
fieldLabel: gettext('Pool to backup'), fieldLabel: gettext('Pool to backup'),
hidden: true, hidden: true,
allowBlank: true, allowBlank: true,
@ -152,7 +150,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var nodesel = Ext.create('PVE.form.NodeSelector', { let nodesel = Ext.create('PVE.form.NodeSelector', {
name: 'node', name: 'node',
fieldLabel: gettext('Node'), fieldLabel: gettext('Node'),
allowBlank: true, allowBlank: true,
@ -162,7 +160,7 @@ Ext.define('PVE.dc.BackupEdit', {
listeners: { listeners: {
change: function(f, value) { change: function(f, value) {
storagesel.setNodename(value || 'localhost'); storagesel.setNodename(value || 'localhost');
var mode = selModeField.getValue(); let mode = selModeField.getValue();
store.clearFilter(); store.clearFilter();
store.filterBy(function(rec) { store.filterBy(function(rec) {
return !value || rec.get('node') === value; return !value || rec.get('node') === value;
@ -170,7 +168,6 @@ Ext.define('PVE.dc.BackupEdit', {
if (mode === 'all') { if (mode === 'all') {
sm.selectAll(true); sm.selectAll(true);
} }
if (mode === 'pool') { if (mode === 'pool') {
selectPoolMembers(selPool.value); selectPoolMembers(selPool.value);
} }
@ -178,7 +175,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var column1 = [ let column1 = [
nodesel, nodesel,
storagesel, storagesel,
{ {
@ -202,7 +199,7 @@ Ext.define('PVE.dc.BackupEdit', {
selPool, selPool,
]; ];
var column2 = [ let column2 = [
{ {
xtype: 'textfield', xtype: 'textfield',
fieldLabel: gettext('Send email to'), fieldLabel: gettext('Send email to'),
@ -239,7 +236,7 @@ Ext.define('PVE.dc.BackupEdit', {
vmidField, vmidField,
]; ];
var ipanel = Ext.create('Proxmox.panel.InputPanel', { let ipanel = Ext.create('Proxmox.panel.InputPanel', {
onlineHelp: 'chapter_vzdump', onlineHelp: 'chapter_vzdump',
column1: column1, column1: column1,
column2: column2, column2: column2,
@ -251,7 +248,7 @@ Ext.define('PVE.dc.BackupEdit', {
delete values.node; delete values.node;
} }
var selMode = values.selMode; let selMode = values.selMode;
delete values.selMode; delete values.selMode;
if (selMode === 'all') { if (selMode === 'all') {
@ -273,7 +270,7 @@ Ext.define('PVE.dc.BackupEdit', {
}, },
}); });
var update_vmid_selection = function(list, mode) { let update_vmid_selection = function(list, mode) {
if (mode !== 'all' && mode !== 'pool') { if (mode !== 'all' && mode !== 'pool') {
sm.deselectAll(true); sm.deselectAll(true);
if (list) { if (list) {
@ -288,7 +285,7 @@ Ext.define('PVE.dc.BackupEdit', {
}; };
vmidField.on('change', function(f, value) { vmidField.on('change', function(f, value) {
var mode = selModeField.getValue(); let mode = selModeField.getValue();
update_vmid_selection(value, mode); update_vmid_selection(value, mode);
}); });
@ -319,21 +316,21 @@ Ext.define('PVE.dc.BackupEdit', {
selPool.setVisible(false); selPool.setVisible(false);
selPool.allowBlank = true; selPool.allowBlank = true;
} }
var list = vmidField.getValue(); let list = vmidField.getValue();
update_vmid_selection(list, value); update_vmid_selection(list, value);
}); });
var reload = function() { let reload = function() {
store.load({ store.load({
params: { type: 'vm' }, params: {
type: 'vm',
},
callback: function() { callback: function() {
var node = nodesel.getValue(); let node = nodesel.getValue();
store.clearFilter(); store.clearFilter();
store.filterBy(function(rec) { store.filterBy(rec => !node || node.length === 0 || rec.get('node') === node);
return !node || node.length === 0 || rec.get('node') === node; let list = vmidField.getValue();
}); let mode = selModeField.getValue();
var list = vmidField.getValue();
var mode = selModeField.getValue();
if (mode === 'all') { if (mode === 'all') {
sm.selectAll(true); sm.selectAll(true);
} else if (mode === 'pool') { } else if (mode === 'pool') {
@ -359,7 +356,7 @@ Ext.define('PVE.dc.BackupEdit', {
} else { } else {
me.load({ me.load({
success: function(response, options) { success: function(response, options) {
var data = response.result.data; let data = response.result.data;
data.dow = data.dow.split(','); data.dow = data.dow.split(',');
@ -404,18 +401,12 @@ Ext.define('PVE.dc.BackupDiskTree', {
{ {
type: 'expand', type: 'expand',
tooltip: gettext('Expand All'), tooltip: gettext('Expand All'),
scope: this, callback: panel => panel.expandAll(),
callback: function(panel) {
panel.expandAll();
},
}, },
{ {
type: 'collapse', type: 'collapse',
tooltip: gettext('Collapse All'), tooltip: gettext('Collapse All'),
scope: this, callback: panel => panel.collapseAll(),
callback: function(panel) {
panel.collapseAll();
},
}, },
], ],
@ -432,9 +423,7 @@ Ext.define('PVE.dc.BackupDiskTree', {
} }
return ret; return ret;
} else { } else {
// volume level // extJS needs unique IDs but we only want to show the volumes key from "vmid:key"
// extJS needs unique IDs but we only want to show the
// volumes key from "vmid:key"
return value.split(':')[1] + " - " + record.data.name; return value.split(':')[1] + " - " + record.data.name;
} }
}, },
@ -455,11 +444,11 @@ Ext.define('PVE.dc.BackupDiskTree', {
], ],
reload: function() { reload: function() {
var me = this; let me = this;
var sm = me.getSelectionModel(); let sm = me.getSelectionModel();
Proxmox.Utils.API2Request({ Proxmox.Utils.API2Request({
url: "/cluster/backup/" + me.jobid + "/included_volumes", url: `/cluster/backup/${me.jobid}/included_volumes`,
waitMsgTarget: me, waitMsgTarget: me,
method: 'GET', method: 'GET',
failure: function(response, opts) { failure: function(response, opts) {
@ -514,42 +503,35 @@ Ext.define('PVE.dc.BackupDiskTree', {
listeners: { listeners: {
buffer: 500, buffer: 500,
keyup: function(field) { keyup: function(field) {
let searchValue = field.getValue(); let searchValue = field.getValue().toLowerCase();
searchValue = searchValue.toLowerCase();
me.store.clearFilter(true); me.store.clearFilter(true);
me.store.filterBy(function(record) { me.store.filterBy(function(record) {
let match = false; let data = {};
if (record.data.depth === 0) {
let data = '';
if (record.data.depth == 0) {
return true; return true;
} else if (record.data.depth == 1) { } else if (record.data.depth === 1) {
data = record.data; data = record.data;
} else if (record.data.depth == 2) { } else if (record.data.depth === 2) {
data = record.parentNode.data; data = record.parentNode.data;
} }
Ext.each(['name', 'id', 'type'], function(property) { for (const property in ['name', 'id', 'type']) {
if (data[property] === null) { if (data[property] === null) {
return; continue;
} }
let v = data[property].toString(); let v = data[property].toString();
if (v !== undefined) { if (v !== undefined) {
v = v.toLowerCase(); v = v.toLowerCase();
if (v.includes(searchValue)) { if (v.includes(searchValue)) {
match = true; return true;
return;
} }
} }
}); }
return match; return false;
}); });
}, },
}, },
}, }],
],
}, },
}); });
@ -760,28 +742,23 @@ Ext.define('PVE.dc.BackedGuests', {
listeners: { listeners: {
buffer: 500, buffer: 500,
keyup: function(field) { keyup: function(field) {
let searchValue = field.getValue(); let searchValue = field.getValue().toLowerCase();
searchValue = searchValue.toLowerCase();
me.store.clearFilter(true); me.store.clearFilter(true);
me.store.filterBy(function(record) { me.store.filterBy(function(record) {
let match = false; let data = record.data;
for (const property in ['name', 'id', 'type']) {
Ext.each(['name', 'vmid', 'type'], function(property) { if (data[property] === null) {
if (record.data[property] == null) { continue;
return;
} }
let v = data[property].toString();
let v = record.data[property].toString();
if (v !== undefined) { if (v !== undefined) {
v = v.toLowerCase(); v = v.toLowerCase();
if (v.includes(searchValue)) { if (v.includes(searchValue)) {
match = true; return true;
return;
} }
} }
}); }
return match; return false;
}); });
}, },
}, },
@ -806,9 +783,9 @@ Ext.define('PVE.dc.BackupView', {
allText: '-- ' + gettext('All') + ' --', allText: '-- ' + gettext('All') + ' --',
initComponent: function() { initComponent: function() {
var me = this; let me = this;
var store = new Ext.data.Store({ let store = new Ext.data.Store({
model: 'pve-cluster-backup', model: 'pve-cluster-backup',
proxy: { proxy: {
type: 'proxmox', type: 'proxmox',
@ -816,7 +793,7 @@ Ext.define('PVE.dc.BackupView', {
}, },
}); });
var not_backed_store = new Ext.data.Store({ let not_backed_store = new Ext.data.Store({
sorters: 'vmid', sorters: 'vmid',
proxy: { proxy: {
type: 'proxmox', type: 'proxmox',
@ -824,53 +801,37 @@ Ext.define('PVE.dc.BackupView', {
}, },
}); });
var reload = function() { let noBackupJobWarning, noBackupJobInfoButton;
let reload = function() {
store.load(); store.load();
not_backed_store.load({ not_backed_store.load({
callback: function(records, operation, success) { callback: function(records, operation, success) {
if (records.length) { noBackupJobWarning.setVisible(records.length > 0);
not_backed_warning.setVisible(true); noBackupJobInfoButton.setVisible(records.length > 0);
not_backed_btn.setVisible(true);
} else {
not_backed_warning.setVisible(false);
not_backed_btn.setVisible(false);
}
}, },
}); });
}; };
var sm = Ext.create('Ext.selection.RowModel', {}); let sm = Ext.create('Ext.selection.RowModel', {});
var run_editor = function() { let run_editor = function() {
var rec = sm.getSelection()[0]; let rec = sm.getSelection()[0];
if (!rec) { if (!rec) {
return; return;
} }
var win = Ext.create('PVE.dc.BackupEdit', { let win = Ext.create('PVE.dc.BackupEdit', {
jobid: rec.data.id, jobid: rec.data.id,
}); });
win.on('destroy', reload); win.on('destroy', reload);
win.show(); win.show();
}; };
var run_detail = function() { let run_detail = function() {
let me = this;
let record = sm.getSelection()[0]; let record = sm.getSelection()[0];
if (!record) { if (!record) {
return; return;
} }
let infoview = Ext.create('PVE.dc.BackupInfo', {
flex: 0,
layout: 'fit',
record: record.data,
});
let disktree = Ext.create('PVE.dc.BackupDiskTree', {
title: gettext('Included disks'),
flex: 1,
jobid: record.data.id,
});
Ext.create('Ext.window.Window', { Ext.create('Ext.window.Window', {
modal: true, modal: true,
width: 800, width: 800,
@ -880,20 +841,34 @@ Ext.define('PVE.dc.BackupView', {
resizable: true, resizable: true,
layout: 'fit', layout: 'fit',
title: gettext('Backup Details'), title: gettext('Backup Details'),
items: [
items: [{ {
xtype: 'panel', xtype: 'panel',
region: 'center', region: 'center',
layout: { layout: {
type: 'vbox', type: 'vbox',
align: 'stretch', align: 'stretch',
}, },
items: [infoview, disktree], items: [
}], {
xtype: 'pveBackupInfo',
flex: 0,
layout: 'fit',
record: record.data,
},
{
xtype: 'pveBackupDiskTree',
title: gettext('Included disks'),
flex: 1,
jobid: record.data.id,
},
],
},
],
}).show(); }).show();
}; };
var run_backup_now = function(job) { let run_backup_now = function(job) {
job = Ext.clone(job); job = Ext.clone(job);
let jobNode = job.node; let jobNode = job.node;
@ -917,8 +892,7 @@ Ext.define('PVE.dc.BackupView', {
nodes = [jobNode]; nodes = [jobNode];
} else { } else {
let unkownNodes = allNodes.filter(node => node.status !== 'online'); let unkownNodes = allNodes.filter(node => node.status !== 'online');
if (unkownNodes.length > 0) if (unkownNodes.length > 0) {errors.push(unkownNodes.map(node => node.node + ": " + gettext("Node is offline")));}
errors.push(unkownNodes.map(node => node.node + ": " + gettext("Node is offline")));
} }
let jobTotalCount = nodes.length, jobsStarted = 0; let jobTotalCount = nodes.length, jobsStarted = 0;
@ -933,7 +907,7 @@ Ext.define('PVE.dc.BackupView', {
jobsStarted++; jobsStarted++;
Ext.Msg.updateProgress(jobsStarted / jobTotalCount, jobsStarted + '/' + jobTotalCount); Ext.Msg.updateProgress(jobsStarted / jobTotalCount, jobsStarted + '/' + jobTotalCount);
if (jobsStarted == jobTotalCount) { if (jobsStarted === jobTotalCount) {
Ext.Msg.hide(); Ext.Msg.hide();
if (errors.length > 0) { if (errors.length > 0) {
Ext.Msg.alert('Error', 'Some errors have been encountered:<br />' + errors.join('<br />')); Ext.Msg.alert('Error', 'Some errors have been encountered:<br />' + errors.join('<br />'));
@ -953,31 +927,32 @@ Ext.define('PVE.dc.BackupView', {
})); }));
}; };
var run_show_not_backed = function() { let run_show_not_backed = function() {
var me = this; Ext.create('Ext.window.Window', {
var backedinfo = Ext.create('PVE.dc.BackedGuests', {
flex: 1,
layout: 'fit',
store: not_backed_store,
});
var win = Ext.create('Ext.window.Window', {
modal: true, modal: true,
width: 600, width: 600,
height: 500, height: 500,
resizable: true, resizable: true,
layout: 'fit', layout: 'fit',
title: gettext('Guests without backup job'), title: gettext('Guests without backup job'),
items: [
items: [{ {
xtype: 'panel', xtype: 'panel',
region: 'center', region: 'center',
layout: { layout: {
type: 'vbox', type: 'vbox',
align: 'stretch', align: 'stretch',
}, },
items: [backedinfo], items: [
}], {
xtype: 'pveBackedGuests',
flex: 1,
layout: 'fit',
store: not_backed_store,
},
],
},
],
}).show(); }).show();
}; };
@ -1029,12 +1004,12 @@ Ext.define('PVE.dc.BackupView', {
handler: run_detail, handler: run_detail,
}); });
var not_backed_warning = Ext.create('Ext.toolbar.TextItem', { noBackupJobWarning = Ext.create('Ext.toolbar.TextItem', {
html: '<i class="fa fa-fw fa-exclamation-circle"></i>' + gettext('Some guests are not covered by any backup job.'), html: '<i class="fa fa-fw fa-exclamation-circle"></i>' + gettext('Some guests are not covered by any backup job.'),
hidden: true, hidden: true,
}); });
var not_backed_btn = new Proxmox.button.Button({ noBackupJobInfoButton = new Proxmox.button.Button({
text: gettext('Show'), text: gettext('Show'),
hidden: true, hidden: true,
handler: run_show_not_backed, handler: run_show_not_backed,
@ -1066,8 +1041,8 @@ Ext.define('PVE.dc.BackupView', {
'-', '-',
run_btn, run_btn,
'->', '->',
not_backed_warning, noBackupJobWarning,
not_backed_btn, noBackupJobInfoButton,
], ],
columns: [ columns: [
{ {
@ -1131,9 +1106,17 @@ Ext.define('PVE.dc.BackupView', {
Ext.define('pve-cluster-backup', { Ext.define('pve-cluster-backup', {
extend: 'Ext.data.Model', extend: 'Ext.data.Model',
fields: [ fields: [
'id', 'starttime', 'dow', 'id',
'storage', 'node', 'vmid', 'exclude', 'compress',
'mailto', 'pool', 'compress', 'mode', 'dow',
'exclude',
'mailto',
'mode',
'node',
'pool',
'starttime',
'storage',
'vmid',
{ name: 'enabled', type: 'boolean' }, { name: 'enabled', type: 'boolean' },
{ name: 'all', type: 'boolean' }, { name: 'all', type: 'boolean' },
], ],