ui: backup job detail view: factor out to own file
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
3071423551
commit
8d26335729
@ -124,6 +124,7 @@ JSSRC= \
|
||||
dc/AuthEditLDAP.js \
|
||||
dc/AuthEditOpenId.js \
|
||||
dc/AuthView.js \
|
||||
dc/BackupJobDetail.js \
|
||||
dc/Backup.js \
|
||||
dc/Cluster.js \
|
||||
dc/ClusterEdit.js \
|
||||
|
@ -428,495 +428,6 @@ 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'),
|
||||
callback: panel => panel.expandAll(),
|
||||
},
|
||||
{
|
||||
type: 'collapse',
|
||||
tooltip: gettext('Collapse All'),
|
||||
callback: panel => panel.collapseAll(),
|
||||
},
|
||||
],
|
||||
|
||||
columns: [
|
||||
{
|
||||
xtype: 'treecolumn',
|
||||
text: gettext('Guest Image'),
|
||||
renderer: function(value, meta, record) {
|
||||
if (record.data.type) {
|
||||
// guest level
|
||||
let ret = value;
|
||||
if (record.data.name) {
|
||||
ret += " (" + record.data.name + ")";
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
// extJS needs unique IDs but we only want to show the volumes key from "vmid:key"
|
||||
return value.split(':')[1] + " - " + record.data.name;
|
||||
}
|
||||
},
|
||||
dataIndex: 'id',
|
||||
flex: 6,
|
||||
},
|
||||
{
|
||||
text: gettext('Type'),
|
||||
dataIndex: 'type',
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
text: gettext('Backup Job'),
|
||||
renderer: PVE.Utils.render_backup_status,
|
||||
dataIndex: 'included',
|
||||
flex: 3,
|
||||
},
|
||||
],
|
||||
|
||||
reload: function() {
|
||||
let me = this;
|
||||
let sm = me.getSelectionModel();
|
||||
|
||||
Proxmox.Utils.API2Request({
|
||||
url: `/cluster/backup/${me.jobid}/included_volumes`,
|
||||
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 && !data.type) {
|
||||
return txt + 'hdd-o';
|
||||
} else if (data.type === 'qemu') {
|
||||
return txt + 'desktop';
|
||||
} else if (data.type === 'lxc') {
|
||||
return txt + 'cube';
|
||||
} else {
|
||||
return txt + 'question-circle';
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
header: {
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
fieldLabel: gettext('Search'),
|
||||
labelWidth: 50,
|
||||
emptyText: 'Name, VMID, Type',
|
||||
width: 200,
|
||||
padding: '0 5 0 0',
|
||||
enableKeyEvents: true,
|
||||
listeners: {
|
||||
buffer: 500,
|
||||
keyup: function(field) {
|
||||
let searchValue = field.getValue().toLowerCase();
|
||||
me.store.clearFilter(true);
|
||||
me.store.filterBy(function(record) {
|
||||
let data = {};
|
||||
if (record.data.depth === 0) {
|
||||
return true;
|
||||
} else if (record.data.depth === 1) {
|
||||
data = record.data;
|
||||
} else if (record.data.depth === 2) {
|
||||
data = record.parentNode.data;
|
||||
}
|
||||
|
||||
for (const property of ['name', 'id', 'type']) {
|
||||
if (!data[property]) {
|
||||
continue;
|
||||
}
|
||||
let v = data[property].toString();
|
||||
if (v !== undefined) {
|
||||
v = v.toLowerCase();
|
||||
if (v.includes(searchValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
},
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
me.callParent();
|
||||
|
||||
me.reload();
|
||||
},
|
||||
});
|
||||
|
||||
Ext.define('PVE.dc.BackupInfo', {
|
||||
extend: 'Proxmox.panel.InputPanel',
|
||||
alias: 'widget.pveBackupInfo',
|
||||
|
||||
viewModel: {
|
||||
data: {
|
||||
retentionType: 'none',
|
||||
},
|
||||
formulas: {
|
||||
hasRetention: (get) => get('retentionType') !== 'none',
|
||||
retentionKeepAll: (get) => get('retentionType') === 'all',
|
||||
},
|
||||
},
|
||||
|
||||
padding: '5 0 5 10',
|
||||
|
||||
column1: [
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'node',
|
||||
fieldLabel: gettext('Node'),
|
||||
renderer: value => value || `-- ${gettext('All')} --`,
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'storage',
|
||||
fieldLabel: gettext('Storage'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'dow',
|
||||
fieldLabel: gettext('Day of week'),
|
||||
renderer: PVE.Utils.render_backup_days_of_week,
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'starttime',
|
||||
fieldLabel: gettext('Start Time'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'selMode',
|
||||
fieldLabel: gettext('Selection mode'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'pool',
|
||||
fieldLabel: gettext('Pool to backup'),
|
||||
},
|
||||
],
|
||||
column2: [
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'mailnotification',
|
||||
fieldLabel: gettext('Email notification'),
|
||||
renderer: function(value) {
|
||||
let mailto = this.up('pveBackupInfo')?.record?.mailto || 'root@localhost';
|
||||
let when = gettext('Always');
|
||||
if (value === 'failure') {
|
||||
when = gettext('On failure only');
|
||||
}
|
||||
return `${when} (${mailto})`;
|
||||
},
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'compress',
|
||||
fieldLabel: gettext('Compression'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'mode',
|
||||
fieldLabel: gettext('Mode'),
|
||||
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;
|
||||
},
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'enabled',
|
||||
fieldLabel: gettext('Enabled'),
|
||||
renderer: v => PVE.Parser.parseBoolean(v.toString()) ? gettext('Yes') : gettext('No'),
|
||||
},
|
||||
],
|
||||
|
||||
columnB: [
|
||||
{
|
||||
xtype: 'label',
|
||||
name: 'pruneLabel',
|
||||
text: gettext('Retention Configuration') + ':',
|
||||
bind: {
|
||||
hidden: '{!hasRetention}',
|
||||
},
|
||||
},
|
||||
{
|
||||
layout: 'hbox',
|
||||
border: false,
|
||||
defaults: {
|
||||
border: false,
|
||||
layout: 'anchor',
|
||||
flex: 1,
|
||||
},
|
||||
items: [
|
||||
{
|
||||
padding: '0 10 0 0',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [{
|
||||
xtype: 'displayfield',
|
||||
name: 'keep-all',
|
||||
fieldLabel: gettext('Keep All'),
|
||||
renderer: Proxmox.Utils.format_boolean,
|
||||
bind: {
|
||||
hidden: '{!retentionKeepAll}',
|
||||
},
|
||||
}].concat(
|
||||
[
|
||||
['keep-last', gettext('Keep Last')],
|
||||
['keep-hourly', gettext('Keep Hourly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
padding: '0 0 0 10',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [
|
||||
['keep-daily', gettext('Keep Daily')],
|
||||
['keep-weekly', gettext('Keep Weekly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
padding: '0 0 0 10',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [
|
||||
['keep-monthly', gettext('Keep Monthly')],
|
||||
['keep-yearly', gettext('Keep Yearly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
setValues: function(values) {
|
||||
var me = this;
|
||||
let vm = me.getViewModel();
|
||||
|
||||
Ext.iterate(values, function(fieldId, val) {
|
||||
let field = me.query('[isFormField][name=' + fieldId + ']')[0];
|
||||
if (field) {
|
||||
field.setValue(val);
|
||||
}
|
||||
});
|
||||
|
||||
if (values['prune-backups'] || values.maxfiles !== undefined) {
|
||||
let keepValues;
|
||||
if (values['prune-backups']) {
|
||||
keepValues = values['prune-backups'];
|
||||
} else if (values.maxfiles > 0) {
|
||||
keepValues = { 'keep-last': values.maxfiles };
|
||||
} else {
|
||||
keepValues = { 'keep-all': 1 };
|
||||
}
|
||||
|
||||
vm.set('retentionType', keepValues['keep-all'] ? 'all' : 'other');
|
||||
|
||||
// set values of all keep-X fields
|
||||
['all', 'last', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'].forEach(time => {
|
||||
let name = `keep-${time}`;
|
||||
me.query(`[isFormField][name=${name}]`)[0]?.setValue(keepValues[name]);
|
||||
});
|
||||
} else {
|
||||
vm.set('retentionType', 'none');
|
||||
}
|
||||
|
||||
// selection Mode depends on the presence/absence of several keys
|
||||
let selModeField = me.query('[isFormField][name=selMode]')[0];
|
||||
let selMode = 'none';
|
||||
if (values.vmid) {
|
||||
selMode = gettext('Include selected VMs');
|
||||
}
|
||||
if (values.all) {
|
||||
selMode = gettext('All');
|
||||
}
|
||||
if (values.exclude) {
|
||||
selMode = gettext('Exclude selected VMs');
|
||||
}
|
||||
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.BackedGuests', {
|
||||
extend: 'Ext.grid.GridPanel',
|
||||
alias: 'widget.pveBackedGuests',
|
||||
|
||||
textfilter: '',
|
||||
|
||||
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,
|
||||
},
|
||||
],
|
||||
|
||||
initComponent: function() {
|
||||
let me = this;
|
||||
|
||||
me.store.clearFilter(true);
|
||||
|
||||
Ext.apply(me, {
|
||||
stateful: true,
|
||||
stateId: 'grid-dc-backed-guests',
|
||||
tbar: [
|
||||
'->',
|
||||
gettext('Search') + ':', ' ',
|
||||
{
|
||||
xtype: 'textfield',
|
||||
width: 200,
|
||||
emptyText: 'Name, VMID, Type',
|
||||
enableKeyEvents: true,
|
||||
listeners: {
|
||||
buffer: 500,
|
||||
keyup: function(field) {
|
||||
let searchValue = field.getValue().toLowerCase();
|
||||
me.store.clearFilter(true);
|
||||
me.store.filterBy(function(record) {
|
||||
let data = record.data;
|
||||
for (const property in ['name', 'id', 'type']) {
|
||||
if (data[property] === null) {
|
||||
continue;
|
||||
}
|
||||
let v = data[property].toString();
|
||||
if (v !== undefined) {
|
||||
v = v.toLowerCase();
|
||||
if (v.includes(searchValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
viewConfig: {
|
||||
stripeRows: true,
|
||||
trackOver: false,
|
||||
},
|
||||
});
|
||||
me.callParent();
|
||||
},
|
||||
});
|
||||
|
||||
Ext.define('PVE.dc.BackupView', {
|
||||
extend: 'Ext.grid.GridPanel',
|
||||
|
||||
|
488
www/manager6/dc/BackupJobDetail.js
Normal file
488
www/manager6/dc/BackupJobDetail.js
Normal file
@ -0,0 +1,488 @@
|
||||
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'),
|
||||
callback: panel => panel.expandAll(),
|
||||
},
|
||||
{
|
||||
type: 'collapse',
|
||||
tooltip: gettext('Collapse All'),
|
||||
callback: panel => panel.collapseAll(),
|
||||
},
|
||||
],
|
||||
|
||||
columns: [
|
||||
{
|
||||
xtype: 'treecolumn',
|
||||
text: gettext('Guest Image'),
|
||||
renderer: function(value, meta, record) {
|
||||
if (record.data.type) {
|
||||
// guest level
|
||||
let ret = value;
|
||||
if (record.data.name) {
|
||||
ret += " (" + record.data.name + ")";
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
// extJS needs unique IDs but we only want to show the volumes key from "vmid:key"
|
||||
return value.split(':')[1] + " - " + record.data.name;
|
||||
}
|
||||
},
|
||||
dataIndex: 'id',
|
||||
flex: 6,
|
||||
},
|
||||
{
|
||||
text: gettext('Type'),
|
||||
dataIndex: 'type',
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
text: gettext('Backup Job'),
|
||||
renderer: PVE.Utils.render_backup_status,
|
||||
dataIndex: 'included',
|
||||
flex: 3,
|
||||
},
|
||||
],
|
||||
|
||||
reload: function() {
|
||||
let me = this;
|
||||
let sm = me.getSelectionModel();
|
||||
|
||||
Proxmox.Utils.API2Request({
|
||||
url: `/cluster/backup/${me.jobid}/included_volumes`,
|
||||
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 && !data.type) {
|
||||
return txt + 'hdd-o';
|
||||
} else if (data.type === 'qemu') {
|
||||
return txt + 'desktop';
|
||||
} else if (data.type === 'lxc') {
|
||||
return txt + 'cube';
|
||||
} else {
|
||||
return txt + 'question-circle';
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
header: {
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
fieldLabel: gettext('Search'),
|
||||
labelWidth: 50,
|
||||
emptyText: 'Name, VMID, Type',
|
||||
width: 200,
|
||||
padding: '0 5 0 0',
|
||||
enableKeyEvents: true,
|
||||
listeners: {
|
||||
buffer: 500,
|
||||
keyup: function(field) {
|
||||
let searchValue = field.getValue().toLowerCase();
|
||||
me.store.clearFilter(true);
|
||||
me.store.filterBy(function(record) {
|
||||
let data = {};
|
||||
if (record.data.depth === 0) {
|
||||
return true;
|
||||
} else if (record.data.depth === 1) {
|
||||
data = record.data;
|
||||
} else if (record.data.depth === 2) {
|
||||
data = record.parentNode.data;
|
||||
}
|
||||
|
||||
for (const property of ['name', 'id', 'type']) {
|
||||
if (!data[property]) {
|
||||
continue;
|
||||
}
|
||||
let v = data[property].toString();
|
||||
if (v !== undefined) {
|
||||
v = v.toLowerCase();
|
||||
if (v.includes(searchValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
},
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
me.callParent();
|
||||
|
||||
me.reload();
|
||||
},
|
||||
});
|
||||
|
||||
Ext.define('PVE.dc.BackupInfo', {
|
||||
extend: 'Proxmox.panel.InputPanel',
|
||||
alias: 'widget.pveBackupInfo',
|
||||
|
||||
viewModel: {
|
||||
data: {
|
||||
retentionType: 'none',
|
||||
},
|
||||
formulas: {
|
||||
hasRetention: (get) => get('retentionType') !== 'none',
|
||||
retentionKeepAll: (get) => get('retentionType') === 'all',
|
||||
},
|
||||
},
|
||||
|
||||
padding: '5 0 5 10',
|
||||
|
||||
column1: [
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'node',
|
||||
fieldLabel: gettext('Node'),
|
||||
renderer: value => value || `-- ${gettext('All')} --`,
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'storage',
|
||||
fieldLabel: gettext('Storage'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'dow',
|
||||
fieldLabel: gettext('Day of week'),
|
||||
renderer: PVE.Utils.render_backup_days_of_week,
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'starttime',
|
||||
fieldLabel: gettext('Start Time'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'selMode',
|
||||
fieldLabel: gettext('Selection mode'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'pool',
|
||||
fieldLabel: gettext('Pool to backup'),
|
||||
},
|
||||
],
|
||||
column2: [
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'mailnotification',
|
||||
fieldLabel: gettext('Email notification'),
|
||||
renderer: function(value) {
|
||||
let mailto = this.up('pveBackupInfo')?.record?.mailto || 'root@localhost';
|
||||
let when = gettext('Always');
|
||||
if (value === 'failure') {
|
||||
when = gettext('On failure only');
|
||||
}
|
||||
return `${when} (${mailto})`;
|
||||
},
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'compress',
|
||||
fieldLabel: gettext('Compression'),
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'mode',
|
||||
fieldLabel: gettext('Mode'),
|
||||
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;
|
||||
},
|
||||
},
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
name: 'enabled',
|
||||
fieldLabel: gettext('Enabled'),
|
||||
renderer: v => PVE.Parser.parseBoolean(v.toString()) ? gettext('Yes') : gettext('No'),
|
||||
},
|
||||
],
|
||||
|
||||
columnB: [
|
||||
{
|
||||
xtype: 'label',
|
||||
name: 'pruneLabel',
|
||||
text: gettext('Retention Configuration') + ':',
|
||||
bind: {
|
||||
hidden: '{!hasRetention}',
|
||||
},
|
||||
},
|
||||
{
|
||||
layout: 'hbox',
|
||||
border: false,
|
||||
defaults: {
|
||||
border: false,
|
||||
layout: 'anchor',
|
||||
flex: 1,
|
||||
},
|
||||
items: [
|
||||
{
|
||||
padding: '0 10 0 0',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [{
|
||||
xtype: 'displayfield',
|
||||
name: 'keep-all',
|
||||
fieldLabel: gettext('Keep All'),
|
||||
renderer: Proxmox.Utils.format_boolean,
|
||||
bind: {
|
||||
hidden: '{!retentionKeepAll}',
|
||||
},
|
||||
}].concat(
|
||||
[
|
||||
['keep-last', gettext('Keep Last')],
|
||||
['keep-hourly', gettext('Keep Hourly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
{
|
||||
padding: '0 0 0 10',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [
|
||||
['keep-daily', gettext('Keep Daily')],
|
||||
['keep-weekly', gettext('Keep Weekly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
padding: '0 0 0 10',
|
||||
defaults: {
|
||||
labelWidth: 110,
|
||||
},
|
||||
items: [
|
||||
['keep-monthly', gettext('Keep Monthly')],
|
||||
['keep-yearly', gettext('Keep Yearly')],
|
||||
].map(
|
||||
name => ({
|
||||
xtype: 'displayfield',
|
||||
name: name[0],
|
||||
fieldLabel: name[1],
|
||||
bind: {
|
||||
hidden: '{!hasRetention || retentionKeepAll}',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
setValues: function(values) {
|
||||
var me = this;
|
||||
let vm = me.getViewModel();
|
||||
|
||||
Ext.iterate(values, function(fieldId, val) {
|
||||
let field = me.query('[isFormField][name=' + fieldId + ']')[0];
|
||||
if (field) {
|
||||
field.setValue(val);
|
||||
}
|
||||
});
|
||||
|
||||
if (values['prune-backups'] || values.maxfiles !== undefined) {
|
||||
let keepValues;
|
||||
if (values['prune-backups']) {
|
||||
keepValues = values['prune-backups'];
|
||||
} else if (values.maxfiles > 0) {
|
||||
keepValues = { 'keep-last': values.maxfiles };
|
||||
} else {
|
||||
keepValues = { 'keep-all': 1 };
|
||||
}
|
||||
|
||||
vm.set('retentionType', keepValues['keep-all'] ? 'all' : 'other');
|
||||
|
||||
// set values of all keep-X fields
|
||||
['all', 'last', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'].forEach(time => {
|
||||
let name = `keep-${time}`;
|
||||
me.query(`[isFormField][name=${name}]`)[0]?.setValue(keepValues[name]);
|
||||
});
|
||||
} else {
|
||||
vm.set('retentionType', 'none');
|
||||
}
|
||||
|
||||
// selection Mode depends on the presence/absence of several keys
|
||||
let selModeField = me.query('[isFormField][name=selMode]')[0];
|
||||
let selMode = 'none';
|
||||
if (values.vmid) {
|
||||
selMode = gettext('Include selected VMs');
|
||||
}
|
||||
if (values.all) {
|
||||
selMode = gettext('All');
|
||||
}
|
||||
if (values.exclude) {
|
||||
selMode = gettext('Exclude selected VMs');
|
||||
}
|
||||
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.BackedGuests', {
|
||||
extend: 'Ext.grid.GridPanel',
|
||||
alias: 'widget.pveBackedGuests',
|
||||
|
||||
stateful: true,
|
||||
stateId: 'grid-dc-backed-guests',
|
||||
|
||||
textfilter: '',
|
||||
|
||||
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,
|
||||
},
|
||||
],
|
||||
viewConfig: {
|
||||
stripeRows: true,
|
||||
trackOver: false,
|
||||
},
|
||||
|
||||
initComponent: function() {
|
||||
let me = this;
|
||||
|
||||
me.store.clearFilter(true);
|
||||
|
||||
Ext.apply(me, {
|
||||
tbar: [
|
||||
'->',
|
||||
gettext('Search') + ':',
|
||||
' ',
|
||||
{
|
||||
xtype: 'textfield',
|
||||
width: 200,
|
||||
emptyText: 'Name, VMID, Type',
|
||||
enableKeyEvents: true,
|
||||
listeners: {
|
||||
buffer: 500,
|
||||
keyup: function(field) {
|
||||
let searchValue = field.getValue().toLowerCase();
|
||||
me.store.clearFilter(true);
|
||||
me.store.filterBy(function(record) {
|
||||
let data = record.data;
|
||||
for (const property in ['name', 'id', 'type']) {
|
||||
if (data[property] === null) {
|
||||
continue;
|
||||
}
|
||||
let v = data[property].toString();
|
||||
if (v !== undefined) {
|
||||
if (v.toLowerCase().includes(searchValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
me.callParent();
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user