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:
kenneth@hexad.dk
2012-06-06 13:01:53 +00:00
parent 11c8f232b7
commit d44595a616
7 changed files with 246 additions and 53 deletions
+45 -25
View File
@@ -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');
}
})
+69 -25
View File
@@ -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();
}
}
});
+2 -1
View File
@@ -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" />