2021-09-09 18:45:13 +03:00
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' ,
2021-11-08 16:07:58 +03:00
name : 'schedule' ,
fieldLabel : gettext ( 'Schedule' ) ,
2021-09-09 18:45:13 +03:00
} ,
{
xtype : 'displayfield' ,
2022-01-13 18:49:38 +03:00
name : 'next-run' ,
fieldLabel : gettext ( 'Next Run' ) ,
renderer : PVE . Utils . render _next _event ,
} ,
{
xtype : 'displayfield' ,
2021-09-09 18:45:13 +03:00
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 ) {
2023-01-19 18:16:49 +03:00
const modeToDisplay = {
snapshot : gettext ( 'Snapshot' ) ,
stop : gettext ( 'Stop' ) ,
suspend : gettext ( 'Snapshot' ) ,
} ;
return modeToDisplay [ value ] ? ? gettext ( 'Unknown' ) ;
2021-09-09 18:45:13 +03:00
} ,
} ,
{
xtype : 'displayfield' ,
name : 'enabled' ,
fieldLabel : gettext ( 'Enabled' ) ,
renderer : v => PVE . Parser . parseBoolean ( v . toString ( ) ) ? gettext ( 'Yes' ) : gettext ( 'No' ) ,
} ,
] ,
columnB : [
2021-11-10 17:02:56 +03:00
{
xtype : 'displayfield' ,
name : 'comment' ,
fieldLabel : gettext ( 'Comment' ) ,
} ,
2021-09-09 18:45:13 +03:00
{
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 ( ) ;
} ,
} ) ;