Added a "connection lost" dialog, and made the countdown stuff modularized and event based.
Fixed some IE7 compatibility, and included a header so the embedded WebBrowser shows things in IE9 mode (IE7 is default for some reason). git-svn-id: https://duplicati.googlecode.com/svn/trunk@1333 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
@@ -5,7 +5,8 @@ Ext.application({
|
||||
'BackupApp.Service',
|
||||
'BackupApp.Utility',
|
||||
'BackupApp.ListUtility',
|
||||
'BackupApp.view.AboutWindow'
|
||||
'BackupApp.view.AboutWindow',
|
||||
'BackupApp.view.LostConnectionWindow'
|
||||
],
|
||||
|
||||
name: 'BackupApp',
|
||||
@@ -37,32 +38,51 @@ Ext.application({
|
||||
BackupApp.utility = this.utility;
|
||||
|
||||
//Pretend the app can fire the update event, this helps with initialization in controllers
|
||||
this.service.on('current-state-updated', function(e) {
|
||||
var updatedTitle = false;
|
||||
if (e.ActiveScheduleId >= 0) {
|
||||
var store = Ext.getStore('Schedules');
|
||||
if (store != null) {
|
||||
var index = store.find('ID', e.ActiveScheduleId);
|
||||
if (index >= 0) {
|
||||
updatedTitle = true;
|
||||
document.title = 'Duplicati backup - running ' + store.getAt(index).get('Name');
|
||||
this.service.on({
|
||||
'current-state-updated': function(e) {
|
||||
var updatedTitle = false;
|
||||
if (e.ActiveScheduleId >= 0) {
|
||||
var store = Ext.getStore('Schedules');
|
||||
if (store != null) {
|
||||
var index = store.find('ID', e.ActiveScheduleId);
|
||||
if (index >= 0) {
|
||||
updatedTitle = true;
|
||||
document.title = 'Duplicati backup - running ' + store.getAt(index).get('Name');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!updatedTitle)
|
||||
{
|
||||
if (e.SuggestedStatusIcon == 'Paused')
|
||||
document.title = 'Duplicati backup - Paused';
|
||||
else
|
||||
document.title = 'Duplicati backup - Ready';
|
||||
}
|
||||
|
||||
BackupApp.instance.fireEvent('current-state-updated', e);
|
||||
});
|
||||
}
|
||||
|
||||
if (!updatedTitle)
|
||||
{
|
||||
if (e.SuggestedStatusIcon == 'Paused')
|
||||
document.title = 'Duplicati backup - Paused';
|
||||
else
|
||||
document.title = 'Duplicati backup - Ready';
|
||||
}
|
||||
|
||||
this.fireEvent('current-state-updated', e);
|
||||
},
|
||||
|
||||
'lost-connection': function() {
|
||||
BackupApp.view.LostConnectionWindow.show();
|
||||
},
|
||||
|
||||
this.service.on('count-down-pause-timer', function(e) {
|
||||
BackupApp.instance.fireEvent('count-down-pause-timer', e);
|
||||
'reconnected': function() {
|
||||
BackupApp.view.LostConnectionWindow.hide();
|
||||
},
|
||||
|
||||
'lost-connection-retry': function() {
|
||||
BackupApp.view.LostConnectionWindow.setStatusAsRunning();
|
||||
},
|
||||
|
||||
'lost-connection-retry-delay': function(seconds) {
|
||||
BackupApp.view.LostConnectionWindow.setStatusAsWaiting(seconds);
|
||||
},
|
||||
|
||||
'count-down-pause-timer': function(e) {
|
||||
BackupApp.instance.fireEvent('count-down-pause-timer', e);
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
|
||||
//Fetch the current status
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
Ext.define('BackupApp.CountDownHelper', {
|
||||
mixins: {
|
||||
observable: 'Ext.util.Observable'
|
||||
},
|
||||
|
||||
statics: {
|
||||
callbacklookup: [],
|
||||
callbackhelper: function(id) {
|
||||
this.callbacklookup[id].onCallback();
|
||||
}
|
||||
},
|
||||
|
||||
expireTime: null,
|
||||
intervalId : null,
|
||||
|
||||
//Bugfix for extjs
|
||||
hasListeners: {},
|
||||
|
||||
constructor: function(config) {
|
||||
this.addEvents('count-down-tick', 'count-down-complete');
|
||||
},
|
||||
|
||||
isRunning: function() {
|
||||
return this.intervalId != null;
|
||||
},
|
||||
|
||||
start: function(time) {
|
||||
if (this.intervalId != null)
|
||||
this.stop(false);
|
||||
|
||||
this.expireTime = time;
|
||||
BackupApp.CountDownHelper.callbacklookup.push(this);
|
||||
var selfid = BackupApp.CountDownHelper.callbacklookup.length - 1;
|
||||
this.intervalId = window.setInterval('BackupApp.CountDownHelper.callbackhelper(' + selfid + ');', 500);
|
||||
},
|
||||
|
||||
onCallback: function() {
|
||||
var secondsLeft = parseInt((this.expireTime.getTime() - new Date().getTime()) / 1000);
|
||||
this.fireEvent('count-down-tick', Math.max(0, secondsLeft));
|
||||
if (secondsLeft <= 0)
|
||||
this.stop(true);
|
||||
},
|
||||
|
||||
stop: function(activateEvent) {
|
||||
if (this.intervalId != null) {
|
||||
window.clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
|
||||
for(var i = 0; i < BackupApp.CountDownHelper.callbacklookup.length; i++) {
|
||||
if (BackupApp.CountDownHelper.callbacklookup[i] == this) {
|
||||
BackupApp.CountDownHelper.callbacklookup.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (activateEvent || activateEvent === undefined)
|
||||
this.fireEvent('count-down-complete');
|
||||
}
|
||||
|
||||
})
|
||||
@@ -1,17 +1,22 @@
|
||||
Ext.define('BackupApp.Service', {
|
||||
requires: [
|
||||
'BackupApp.CountDownHelper'
|
||||
],
|
||||
mixins: {
|
||||
observable: 'Ext.util.Observable'
|
||||
},
|
||||
|
||||
controlUrl: '/control.cgi',
|
||||
pauseCountDownTimer: null,
|
||||
pauseCountDownHelper: null,
|
||||
lostConnectionCountDownHelper: null,
|
||||
updateRequestParams: {
|
||||
action: 'get-current-state',
|
||||
longpoll: true,
|
||||
lasteventid: '-1',
|
||||
duration: '5m',
|
||||
duration: '5m'
|
||||
},
|
||||
updateRequestRunning: false,
|
||||
updateRequestFailureCount: 0,
|
||||
|
||||
//Bugfix for extjs
|
||||
hasListeners: {},
|
||||
@@ -26,7 +31,36 @@ Ext.define('BackupApp.Service', {
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.addEvents('current-state-updated', 'count-down-pause-timer');
|
||||
this.addEvents('current-state-updated', 'count-down-pause-timer', 'lost-connection', 'reconnected', 'lost-connection-retry', 'lost-connection-retry-delay');
|
||||
this.lostConnectionCountDownHelper = new BackupApp.CountDownHelper();
|
||||
this.pauseCountDownHelper = new BackupApp.CountDownHelper();
|
||||
|
||||
this.pauseCountDownHelper.on({
|
||||
'count-down-tick': function(secondsleft) {
|
||||
this.fireEvent('count-down-pause-timer', secondsleft);
|
||||
},
|
||||
'count-down-complete': function() {
|
||||
this.fireEvent('count-down-pause-timer', 0);
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
|
||||
this.lostConnectionCountDownHelper.on({
|
||||
'count-down-tick': function(seconds) {
|
||||
this.fireEvent('lost-connection-retry-delay', seconds);
|
||||
},
|
||||
'count-down-complete': function() {
|
||||
this.updateCurrentState();
|
||||
this.fireEvent('lost-connection-retry');
|
||||
},
|
||||
scope: this
|
||||
})
|
||||
},
|
||||
|
||||
reconnectNow: function() {
|
||||
if (this.lostConnectionCountDownHelper.isRunning()) {
|
||||
this.lostConnectionCountDownHelper.stop(true);
|
||||
}
|
||||
},
|
||||
|
||||
updateCurrentState: function(force) {
|
||||
@@ -37,7 +71,17 @@ Ext.define('BackupApp.Service', {
|
||||
var timeout = force ? 5000 : (1000 * ((60 * 5) + 5));
|
||||
|
||||
if (!force)
|
||||
{
|
||||
this.updateRequestRunning = true;
|
||||
if (this.updateRequestFailureCount > 0)
|
||||
{
|
||||
//Last request failed, so lets retry,
|
||||
// with a short timeout and make sure we
|
||||
// don't wait for an update
|
||||
timeout = 10000; //10 sec
|
||||
this.updateRequestParams.lasteventid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Ext.Ajax.request({
|
||||
url: this.controlUrl,
|
||||
@@ -48,6 +92,10 @@ Ext.define('BackupApp.Service', {
|
||||
var res = eval('(' + response.responseText + ')');
|
||||
if (res != null)
|
||||
{
|
||||
if (this.updateRequestFailureCount >= 2)
|
||||
this.fireEvent('reconnected');
|
||||
|
||||
this.updateRequestFailureCount = 0;
|
||||
Ext.log('Got update: ' + res.LastEventID + ', last: ' + this.updateRequestParams.lasteventid);
|
||||
var realUpdate = this.updateRequestParams.lasteventid != res.LastEventID;
|
||||
this.serverdata['current-state'] = res;
|
||||
@@ -63,40 +111,36 @@ Ext.define('BackupApp.Service', {
|
||||
if (realUpdate)
|
||||
this.fireEvent('current-state-updated', this.serverdata['current-state']);
|
||||
if (this.getExpectedPauseEnd() != null)
|
||||
this.startPauseCountDownTimer();
|
||||
this.pauseCountDownHelper.start(this.getExpectedPauseEnd());
|
||||
else if (this.pauseCountDownHelper.isRunning())
|
||||
this.pauseCountDownHelper.stop(true);
|
||||
}
|
||||
},
|
||||
failure: function(response, opts) {
|
||||
//TODO: Grey out or similar
|
||||
|
||||
|
||||
//Register next request
|
||||
if (!force)
|
||||
{
|
||||
Ext.log('Failure in longpoll: ' + response.status + ', timeout: ' + response.timedout);
|
||||
|
||||
this.updateRequestFailureCount++;
|
||||
this.updateRequestRunning = false;
|
||||
this.updateCurrentState();
|
||||
|
||||
if (this.updateRequestFailureCount == 2)
|
||||
this.fireEvent('lost-connection');
|
||||
|
||||
if (this.updateRequestFailureCount >= 2) {
|
||||
|
||||
this.lostConnectionCountDownHelper.start(Ext.Date.add(new Date(), Ext.Date.SECOND, 30));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.updateCurrentState();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startPauseCountDownTimer: function() {
|
||||
if (this.pauseCountDownTimer == null)
|
||||
this.pauseCountDownTimer = window.setTimeout('BackupApp.service.onPauseCountDownTimer()', 500);
|
||||
},
|
||||
|
||||
onPauseCountDownTimer: function() {
|
||||
this.pauseCountDownTimer = null;
|
||||
var pauseEnd = this.getExpectedPauseEnd();
|
||||
if (pauseEnd == null) {
|
||||
this.fireEvent('count-down-pause-timer', 0);
|
||||
} else {
|
||||
this.fireEvent('count-down-pause-timer', parseInt((pauseEnd.getTime() - new Date().getTime()) / 1000));
|
||||
this.startPauseCountDownTimer();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getExpectedPauseEnd: function() {
|
||||
var pauseEnd = this.serverdata['current-state'].EstimatedPauseEnd;
|
||||
if (pauseEnd != null) {
|
||||
|
||||
@@ -7,7 +7,7 @@ Ext.define('BackupApp.controller.StatuswindowHeader', {
|
||||
ref: 'pauseButton'
|
||||
}, {
|
||||
selector: '#status-window-header-pause-menu',
|
||||
ref: 'pauseMenu',
|
||||
ref: 'pauseMenu'
|
||||
}],
|
||||
|
||||
init: function() {
|
||||
|
||||
@@ -82,7 +82,7 @@ Ext.define('BackupApp.store.Schedules', {
|
||||
return 0;
|
||||
}
|
||||
}, {
|
||||
property: 'Name',
|
||||
property: 'Name'
|
||||
}],
|
||||
|
||||
proxy: {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
Ext.define('BackupApp.view.LostConnectionWindow', {
|
||||
statics: {
|
||||
dialogWindow: null,
|
||||
setStatusAsRunning: function() {
|
||||
if (this.dialogWindow != null) {
|
||||
var txt = this.dialogWindow.queryById('status-window-lost-connection-text');
|
||||
var btn = this.dialogWindow.queryById('status-window-lost-connection-retry-button');
|
||||
btn.setDisabled(true);
|
||||
txt.setText('Connection to server is lost, retrying ...');
|
||||
}
|
||||
},
|
||||
|
||||
setStatusAsWaiting: function(seconds) {
|
||||
if (BackupApp.service.updateRequestRunning)
|
||||
{
|
||||
this.setStatusAsRunning();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.dialogWindow != null) {
|
||||
var txt = this.dialogWindow.queryById('status-window-lost-connection-text');
|
||||
var btn = this.dialogWindow.queryById('status-window-lost-connection-retry-button');
|
||||
txt.setText('Connection to server is lost, retry in ' + BackupApp.Utility.formatSecondsAsTime(seconds));
|
||||
btn.setDisabled(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (this.dialogWindow != null)
|
||||
this.dialogWindow.hide();
|
||||
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this.dialogWindow == null)
|
||||
this.dialogWindow = Ext.create('Ext.window.Window', {
|
||||
title: 'Lost connection to server',
|
||||
height: 200,
|
||||
width: 400,
|
||||
modal: true,
|
||||
closable: false,
|
||||
resizable: false,
|
||||
buttonAlign: 'center',
|
||||
closeAction: 'hide',
|
||||
layout: 'fit',
|
||||
items: [{
|
||||
xtype: 'label',
|
||||
id: 'status-window-lost-connection-text',
|
||||
text: 'Connection to server is lost, retrying ...'
|
||||
}],
|
||||
buttons: [{
|
||||
xtype: 'button',
|
||||
id: 'status-window-lost-connection-retry-button',
|
||||
text: 'Retry now',
|
||||
disabled: true,
|
||||
handler: function() {
|
||||
BackupApp.service.reconnectNow();
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
this.dialogWindow.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9" />
|
||||
<title>Duplicati Backup</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="extjs-4.1.0/resources/css/ext-all.css" />
|
||||
|
||||
Reference in New Issue
Block a user