2020-05-29 10:53:42 +02:00
Ext . define ( 'pbs-sync-jobs-status' , {
extend : 'Ext.data.Model' ,
fields : [
2022-05-10 15:02:23 +02:00
'id' , 'owner' , 'remote' , 'remote-store' , 'remote-ns' , 'store' , 'ns' ,
'schedule' , 'group-filter' , 'next-run' , 'last-run-upid' , 'last-run-state' ,
2024-04-18 14:01:17 +02:00
'last-run-endtime' , 'transfer-last' , 'max-depth' ,
2020-05-29 10:53:42 +02:00
{
name : 'duration' ,
calculate : function ( data ) {
let endtime = data [ 'last-run-endtime' ] ;
if ( ! endtime ) return undefined ;
let task = Proxmox . Utils . parse _task _upid ( data [ 'last-run-upid' ] ) ;
return endtime - task . starttime ;
} ,
} ,
2020-10-27 16:20:08 +01:00
'comment' ,
2020-05-29 10:53:42 +02:00
] ,
idProperty : 'id' ,
} ) ;
Ext . define ( 'PBS.config.SyncJobView' , {
extend : 'Ext.grid.GridPanel' ,
alias : 'widget.pbsSyncJobView' ,
2024-11-11 16:43:48 +01:00
mixins : [ 'Proxmox.Mixin.CBind' ] ,
2020-05-29 10:53:42 +02:00
stateful : true ,
2020-10-31 10:58:42 +01:00
stateId : 'grid-sync-jobs-v1' ,
2020-05-29 10:53:42 +02:00
2024-11-25 12:15:35 +01:00
title : gettext ( 'Sync Jobs' ) ,
2020-05-29 10:53:42 +02:00
controller : {
xclass : 'Ext.app.ViewController' ,
2024-11-25 12:15:37 +01:00
search : function ( tf , value ) {
let me = this ;
let view = me . getView ( ) ;
let store = view . getStore ( ) ;
if ( ! value && value !== 0 ) {
store . clearFilter ( ) ;
tf . triggers . clear . setVisible ( false ) ;
return ;
}
tf . triggers . clear . setVisible ( true ) ;
if ( value . length < 2 ) return ;
store . clearFilter ( ) ;
2024-11-26 15:47:34 +01:00
let fieldsToSearch = [ 'sync-direction' , 'id' , 'remote' , 'remote-store' , 'owner' ] ;
2024-11-25 12:15:37 +01:00
if ( ! view . datastore ) {
fieldsToSearch . push ( 'store' ) ;
}
value = value . toLowerCase ( ) ;
store . addFilter ( function ( rec ) {
let found = false ;
for ( const field of fieldsToSearch ) {
let recValue = rec . data [ field ] ? ? '' ;
if ( recValue . toString ( ) . toLowerCase ( ) . indexOf ( value ) !== - 1 ) {
found = true ;
break ;
}
}
return found ;
} ) ;
} ,
2024-11-25 12:15:35 +01:00
addPullSyncJob : function ( ) {
this . addSyncJob ( 'pull' ) ;
} ,
addPushSyncJob : function ( ) {
this . addSyncJob ( 'push' ) ;
} ,
addSyncJob : function ( syncDirection ) {
2020-05-29 10:53:42 +02:00
let me = this ;
2020-10-27 16:20:08 +01:00
let view = me . getView ( ) ;
2020-05-29 10:53:42 +02:00
Ext . create ( 'PBS.window.SyncJobEdit' , {
2020-10-27 16:20:08 +01:00
datastore : view . datastore ,
2024-11-25 12:15:35 +01:00
syncDirection ,
2020-05-29 10:53:42 +02:00
listeners : {
destroy : function ( ) {
me . reload ( ) ;
} ,
} ,
} ) . show ( ) ;
} ,
editSyncJob : function ( ) {
let me = this ;
let view = me . getView ( ) ;
let selection = view . getSelection ( ) ;
if ( selection . length < 1 ) return ;
Ext . create ( 'PBS.window.SyncJobEdit' , {
2020-10-27 16:20:08 +01:00
datastore : view . datastore ,
2020-05-29 10:53:42 +02:00
id : selection [ 0 ] . data . id ,
2024-11-26 15:47:34 +01:00
syncDirection : selection [ 0 ] . data [ 'sync-direction' ] ,
2020-05-29 10:53:42 +02:00
listeners : {
destroy : function ( ) {
me . reload ( ) ;
} ,
} ,
} ) . show ( ) ;
} ,
openTaskLog : function ( ) {
let me = this ;
let view = me . getView ( ) ;
let selection = view . getSelection ( ) ;
if ( selection . length < 1 ) return ;
let upid = selection [ 0 ] . data [ 'last-run-upid' ] ;
if ( ! upid ) return ;
Ext . create ( 'Proxmox.window.TaskViewer' , {
2020-09-25 18:40:03 +02:00
upid ,
2020-05-29 10:53:42 +02:00
} ) . show ( ) ;
} ,
runSyncJob : function ( ) {
let me = this ;
let view = me . getView ( ) ;
let selection = view . getSelection ( ) ;
if ( selection . length < 1 ) return ;
let id = selection [ 0 ] . data . id ;
Proxmox . Utils . API2Request ( {
method : 'POST' ,
url : ` /admin/sync/ ${ id } /run ` ,
success : function ( response , opt ) {
Ext . create ( 'Proxmox.window.TaskViewer' , {
upid : response . result . data ,
taskDone : function ( success ) {
me . reload ( ) ;
} ,
} ) . show ( ) ;
} ,
failure : function ( response , opt ) {
Ext . Msg . alert ( gettext ( 'Error' ) , response . htmlStatus ) ;
} ,
} ) ;
} ,
2020-10-30 12:36:41 +01:00
render _optional _owner : function ( value , metadata , record ) {
if ( ! value ) return '-' ;
2022-05-10 15:02:42 +02:00
return Ext . String . htmlEncode ( value ) ;
2020-10-30 12:36:41 +01:00
} ,
2020-10-27 16:20:08 +01:00
startStore : function ( ) { this . getView ( ) . getStore ( ) . rstore . startUpdate ( ) ; } ,
stopStore : function ( ) { this . getView ( ) . getStore ( ) . rstore . stopUpdate ( ) ; } ,
2020-05-29 10:53:42 +02:00
reload : function ( ) { this . getView ( ) . getStore ( ) . rstore . load ( ) ; } ,
init : function ( view ) {
2020-11-09 16:01:25 +01:00
let params = { } ;
if ( view . datastore !== undefined ) {
params . store = view . datastore ;
}
2024-11-25 12:15:35 +01:00
params [ 'sync-direction' ] = 'all' ;
2020-11-09 16:01:25 +01:00
view . getStore ( ) . rstore . getProxy ( ) . setExtraParams ( params ) ;
2020-05-29 10:53:42 +02:00
Proxmox . Utils . monStoreErrors ( view , view . getStore ( ) . rstore ) ;
} ,
} ,
listeners : {
2020-10-27 16:20:08 +01:00
activate : 'startStore' ,
deactivate : 'stopStore' ,
2020-05-29 10:53:42 +02:00
itemdblclick : 'editSyncJob' ,
} ,
store : {
type : 'diff' ,
autoDestroy : true ,
autoDestroyRstore : true ,
2024-11-26 15:47:34 +01:00
sorters : [ 'store' , 'sync-direction' , 'id' ] ,
2020-05-29 10:53:42 +02:00
rstore : {
type : 'update' ,
storeid : 'pbs-sync-jobs-status' ,
model : 'pbs-sync-jobs-status' ,
interval : 5000 ,
2024-11-11 16:43:50 +01:00
proxy : {
type : 'proxmox' ,
url : '/api2/json/admin/sync' ,
} ,
2020-05-29 10:53:42 +02:00
} ,
} ,
tbar : [
{
text : gettext ( 'Add' ) ,
2024-11-25 12:15:35 +01:00
menu : [
{
text : gettext ( 'Add Pull Sync Job' ) ,
iconCls : "fa fa-fw fa-download" ,
handler : 'addPullSyncJob' ,
selModel : false ,
} ,
{
text : gettext ( 'Add Push Sync Job' ) ,
iconCls : "fa fa-fw fa-upload" ,
handler : 'addPushSyncJob' ,
selModel : false ,
} ,
] ,
2020-05-29 10:53:42 +02:00
} ,
{
xtype : 'proxmoxButton' ,
text : gettext ( 'Edit' ) ,
handler : 'editSyncJob' ,
disabled : true ,
} ,
{
xtype : 'proxmoxStdRemoveButton' ,
baseurl : '/config/sync/' ,
2020-10-29 14:34:31 +01:00
confirmMsg : gettext ( 'Remove entry?' ) ,
2020-05-29 10:53:42 +02:00
callback : 'reload' ,
} ,
'-' ,
{
xtype : 'proxmoxButton' ,
2020-10-28 21:25:30 +01:00
text : gettext ( 'Show Log' ) ,
2020-05-29 10:53:42 +02:00
handler : 'openTaskLog' ,
enableFn : ( rec ) => ! ! rec . data [ 'last-run-upid' ] ,
disabled : true ,
} ,
{
xtype : 'proxmoxButton' ,
text : gettext ( 'Run now' ) ,
handler : 'runSyncJob' ,
disabled : true ,
} ,
2024-11-25 12:15:37 +01:00
'->' ,
{
xtype : 'tbtext' ,
html : gettext ( 'Search' ) ,
} ,
{
xtype : 'textfield' ,
reference : 'searchbox' ,
emptyText : gettext ( '(remote) store, remote, id, owner, direction' ) ,
minWidth : 300 ,
triggers : {
clear : {
cls : 'pmx-clear-trigger' ,
weight : - 1 ,
hidden : true ,
handler : function ( ) {
this . triggers . clear . setVisible ( false ) ;
this . setValue ( '' ) ;
} ,
} ,
} ,
listeners : {
change : {
fn : 'search' ,
buffer : 500 ,
} ,
} ,
} ,
2020-05-29 10:53:42 +02:00
] ,
viewConfig : {
trackOver : false ,
} ,
columns : [
{
2020-10-31 10:54:14 +01:00
header : gettext ( 'Job ID' ) ,
2020-05-29 10:53:42 +02:00
dataIndex : 'id' ,
2020-10-28 21:25:30 +01:00
renderer : Ext . String . htmlEncode ,
2020-10-31 10:54:14 +01:00
maxWidth : 220 ,
minWidth : 75 ,
flex : 1 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
2024-11-25 12:15:35 +01:00
{
header : gettext ( 'Direction' ) ,
2024-11-26 15:47:34 +01:00
dataIndex : 'sync-direction' ,
2024-11-25 12:15:35 +01:00
renderer : function ( value ) {
let iconCls , text ;
2024-11-26 15:47:34 +01:00
if ( value === 'push' ) {
2024-11-25 12:15:35 +01:00
iconCls = 'upload' ;
text = gettext ( 'Push' ) ;
2024-11-26 15:47:34 +01:00
} else {
iconCls = 'download' ;
text = gettext ( 'Pull' ) ;
2024-11-25 12:15:35 +01:00
}
return ` <i class="fa fa-fw fa- ${ iconCls } "></i> ${ text } ` ;
} ,
width : 100 ,
sortable : true ,
} ,
2020-05-29 10:53:42 +02:00
{
2020-11-10 13:18:01 +01:00
header : gettext ( 'Local Store' ) ,
dataIndex : 'store' ,
2020-10-31 10:54:14 +01:00
width : 120 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
2022-05-10 15:02:23 +02:00
{
header : gettext ( 'Namespace' ) ,
dataIndex : 'ns' ,
width : 120 ,
sortable : true ,
renderer : PBS . Utils . render _optional _namespace ,
} ,
2020-05-29 10:53:42 +02:00
{
2022-01-12 09:38:20 +01:00
header : gettext ( 'Remote ID' ) ,
2020-11-10 13:18:01 +01:00
dataIndex : 'remote' ,
2020-10-31 10:54:14 +01:00
width : 120 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2023-11-21 15:31:55 +01:00
renderer : PBS . Utils . render _optional _remote ,
2020-05-29 10:53:42 +02:00
} ,
{
2020-11-10 13:18:01 +01:00
header : gettext ( 'Remote Store' ) ,
dataIndex : 'remote-store' ,
2020-10-31 10:54:14 +01:00
width : 120 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
2022-05-10 15:02:23 +02:00
{
header : gettext ( 'Remote Namespace' ) ,
dataIndex : 'remote-ns' ,
width : 120 ,
sortable : true ,
renderer : PBS . Utils . render _optional _namespace ,
} ,
{
2024-04-18 14:01:16 +02:00
header : gettext ( 'Max. Depth' ) ,
2022-05-10 15:02:23 +02:00
dataIndex : 'max-depth' ,
2024-04-18 14:01:18 +02:00
width : 100 ,
2022-05-10 15:02:23 +02:00
sortable : true ,
} ,
2020-10-30 12:36:41 +01:00
{
2024-11-25 12:15:35 +01:00
header : ` ${ gettext ( 'Local Owner/User' ) } <i class="fa fa-question-circle" data-qtip="
$ { gettext ( "Pull: The local owner." ) } < br >
$ { gettext ( "Push: The local user used for access control." ) }
" > < / i > ` ,
2020-10-30 12:36:41 +01:00
dataIndex : 'owner' ,
renderer : 'render_optional_owner' ,
flex : 2 ,
sortable : true ,
} ,
2021-10-28 15:00:54 +02:00
{
header : gettext ( 'Backup Groups' ) ,
2021-11-22 09:02:04 +01:00
dataIndex : 'group-filter' ,
2021-10-28 15:00:54 +02:00
renderer : v => v ? Ext . String . htmlEncode ( v ) : gettext ( 'All' ) ,
width : 80 ,
} ,
2023-04-18 16:59:47 +02:00
{
header : gettext ( 'Transfer Last' ) ,
dataIndex : 'transfer-last' ,
flex : 1 ,
sortable : true ,
hidden : true ,
} ,
2020-05-29 10:53:42 +02:00
{
header : gettext ( 'Schedule' ) ,
dataIndex : 'schedule' ,
2020-10-31 10:54:14 +01:00
maxWidth : 220 ,
minWidth : 80 ,
flex : 1 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
{
header : gettext ( 'Last Sync' ) ,
dataIndex : 'last-run-endtime' ,
2021-02-19 09:14:31 +01:00
renderer : PBS . Utils . render _optional _timestamp ,
2020-10-31 10:54:14 +01:00
width : 150 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
{
text : gettext ( 'Duration' ) ,
dataIndex : 'duration' ,
renderer : Proxmox . Utils . render _duration ,
2020-10-31 10:54:14 +01:00
width : 80 ,
} ,
{
header : gettext ( 'Status' ) ,
dataIndex : 'last-run-state' ,
2021-02-19 09:14:31 +01:00
renderer : PBS . Utils . render _task _status ,
2020-10-31 10:54:14 +01:00
flex : 3 ,
2020-05-29 10:53:42 +02:00
} ,
{
header : gettext ( 'Next Run' ) ,
dataIndex : 'next-run' ,
2021-02-19 09:14:31 +01:00
renderer : PBS . Utils . render _next _task _run ,
2020-10-31 10:54:14 +01:00
width : 150 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
{
header : gettext ( 'Comment' ) ,
dataIndex : 'comment' ,
2020-10-28 21:25:30 +01:00
renderer : Ext . String . htmlEncode ,
2020-10-31 10:54:14 +01:00
flex : 2 ,
2020-10-28 21:25:30 +01:00
sortable : true ,
2020-05-29 10:53:42 +02:00
} ,
] ,
2020-11-10 12:58:00 +01:00
initComponent : function ( ) {
let me = this ;
let hideLocalDatastore = ! ! me . datastore ;
2020-11-10 13:18:01 +01:00
for ( let column of me . columns ) {
if ( column . dataIndex === 'store' ) {
column . hidden = hideLocalDatastore ;
break ;
}
}
2020-11-10 12:58:00 +01:00
me . callParent ( ) ;
} ,
2020-05-29 10:53:42 +02:00
} ) ;