Removed the old ExtJS based UI

This commit is contained in:
Kenneth Skovhede
2013-12-07 15:26:10 +01:00
parent 6f204771b7
commit 25f7920351
56 changed files with 0 additions and 3910 deletions
@@ -1,61 +0,0 @@
Ext.define('Duplicati.CountDownHelper', {
mixins: {
observable: 'Ext.util.Observable'
},
statics: {
callbackkeycounter: 0,
callbacklookup: {},
callbackhelper: function(id) {
this.callbacklookup["" + id].onCallback();
}
},
expireTime: null,
intervalId : null,
constructor: function(config) {
this.mixins.observable.constructor.call(this, 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;
var selfid = Duplicati.CountDownHelper.callbackkeycounter++;
Duplicati.CountDownHelper.callbacklookup["" + selfid] = this;
this.intervalId = window.setInterval('Duplicati.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 k in Duplicati.CountDownHelper.callbacklookup) {
if (Duplicati.CountDownHelper.callbacklookup[k] == this) {
delete Duplicati.CountDownHelper.callbacklookup[k];
break;
}
}
if (activateEvent || activateEvent === undefined)
this.fireEvent('count-down-complete');
}
})
@@ -1,118 +0,0 @@
Ext.define('Duplicati.ListUtility', {
statics: {
currentScheduleId: null,
showContextMenu: function(id, el) {
var lst = Ext.getCmp('status-window-schedule-list');
var mnu = lst.elementContextMenu;
this.currentScheduleId = id;
var elx = Ext.get(el);
mnu.showBy(elx, 'tr-br?');
},
formatSizeString: function(size) { return Duplicati.Utility.formatSizeString(size); },
timeAgo: function(date) { return Duplicati.Utility.timeAgo(date); },
formatCountString: function(count, singular, plural) {
count = parseInt(count);
if (count == 1)
return 1 + ' ' + singluar;
//Make a string
count = count + '';
var tmp = '';
while (count.length > 3) {
tmp = count.substr(count.length - 3, 3) + (tmp.length == 0 ? '' : '.') + tmp;
count = count.substr(0, count.length - 3);
}
tmp = count + (tmp.length == 0 ? '' : '.') + tmp;
return tmp + ' ' + plural;
},
formatBackupScheduleDetails: function(values)
{
var metadata = '';
if (values.Metadata != null)
{
var metadataItems = [];
var mt = values.Metadata;
var sourceData = '';
if (mt['source-file-size'] != null && mt['source-file-count'] != null)
sourceData = this.formatSizeString(mt['source-file-size']) + ' (' + this.formatCountString(mt['source-file-count'], 'file', 'files') + ')';
else if (mt['source-file-size'] != null)
sourceData = this.formatSizeString(mt['source-file-size']);
else if (mt['source-file-count'] != null)
sourceData = this.formatCountString(mt['source-file-count'], 'file', 'files');
if (sourceData != '')
metadataItems.push('<span class="backup-schedule-detail-source-size">Source: ' + sourceData + '</span>');
var backupData = '';
if (mt['total-backup-size'] != null && parseInt(mt['total-backup-size']) > 0 && mt['total-file-count'] != null && parseInt(mt['total-file-count']) > 0)
backupData = this.formatSizeString(mt['total-backup-size']) + ' (' + this.formatCountString(mt['total-file-count'], 'file', 'files') + ')';
else if (mt['total-backup-size'] != null && parseInt(mt['total-backup-size']) > 0)
backupData = this.formatSizeString(mt['total-backup-size']);
else if (mt['total-file-count'] != null && parseInt(mt['total-file-count']) > 0)
backupData = this.formatCountString(mt['total-file-count'], 'file', 'files');
if (backupData != '')
metadataItems.push('<span class="backup-schedule-detail-backup-size">Backup: ' + backupData + '</span>');
if (mt['assigned-quota-space'] != null || mt['free-quota-space'] != null)
{
var spaceLeft = null;
if (mt['assigned-quota-space'] != null && mt['free-quota-space'] != null && mt['total-backup-size'] != null)
spaceLeft = Math.min(parseInt(mt['assigned-quota-space']) - parseInt(mt['total-backup-size']), parseInt(mt['free-quota-space']));
else if (mt['assigned-quota-space'] != null && mt['total-backup-size'] != null)
spaceLeft = parseInt(mt['assigned-quota-space']) - parseInt(mt['total-backup-size']);
else if (mt['free-quota-space'] != null)
spaceLeft = parseInt(mt['free-quota-space']);
var extracls = '';
if (mt['total-backup-size'] != null)
{
//We mark it as low if there is less than 10% free
if (spaceLeft < (parseInt(mt['total-backup-size']) * 0.1))
extracls = 'class="low-storage-space"';
}
if (spaceLeft != null)
metadataItems.push('<span class="backup-schedule-detail-free-size">Free space: <span ' + extracls + '>' + this.formatSizeString(spaceLeft) + '</span></span>');
}
if (mt['changed-file-count'] != null)
{
var changedFiles = parseInt(mt['changed-file-count']);
var str = changedFiles + ' ' + changedFiles == 1 ? "change" : "changes";
if (mt['last-backup-date'] != null)
str += ' since ' + this.timeAgo(new Date(mt['last-backup-date']));
metadataItems.push('<span class="backup-schedule-detail-change-count">' + str + '</span>');
} else if (mt['last-backup-date'] != null || mt['last-backup-completed-time'] != null) {
if (mt['last-backup-completed-time'] != null)
metadataItems.push('<span class="backup-schedule-detail-last-backup">Last backup: <span class="marker-time-ago" title="' + (new Date(mt['last-backup-completed-time'])).toUTCString() + '"></span>' + this.timeAgo(new Date(mt['last-backup-completed-time'])) + '</span>');
else
metadataItems.push('<span class="backup-schedule-detail-last-backup">Last backup: <span class="marker-time-ago" title="' + (new Date(mt['last-backup-date'])).toUTCString() + '"></span>' + this.timeAgo(new Date(mt['last-backup-date'])) + '</span>');
}
for(var ix = 0; ix < metadataItems.length; ix++)
{
/*if (ix != 0)
metadata += ", "; */
metadata += metadataItems[ix];
}
}
if (metadata == '')
metadata = '<span class="important-information">No backup information was found, <a title="Click here to run the backup now" href="#" onclick="Duplicati.service.runBackup(' + values.ID + ', false)">run a backup</a> to obtain data</span>'
return metadata;
}
}
})
@@ -1,319 +0,0 @@
Ext.define('Duplicati.Service', {
requires: [
'Duplicati.CountDownHelper'
],
mixins: {
observable: 'Ext.util.Observable'
},
controlUrl: '/control.cgi',
pauseCountDownHelper: null,
lostConnectionCountDownHelper: null,
updateRequestParams: {
action: 'get-current-state',
longpoll: true,
lasteventid: '-1',
duration: '5m'
},
updateRequestRunning: false,
updateRequestFailureCount: 0,
//Cache for server responses
serverdata: {
'current-state': null,
'installed-backends': null,
'installed-compression-modules': null,
'installed-encryption-modules': null,
'installed-generic-modules': null,
'backup-defaults': null,
'system-info': null
},
constructor: function(config) {
this.mixins.observable.constructor.call(this, config);
this.addEvents('current-state-updated', 'count-down-pause-timer', 'lost-connection', 'reconnected', 'lost-connection-retry', 'lost-connection-retry-delay');
this.lostConnectionCountDownHelper = new Duplicati.CountDownHelper();
this.pauseCountDownHelper = new Duplicati.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
})
this.loadSystemInfo(false);
},
loadSystemInfo: function(reload) {
if (reload || this.serverdata['system-info'] == null) {
Ext.Ajax.request({
url: this.controlUrl,
params: {action: 'system-info'},
scope: this,
success: function(response) {
var res = eval('(' + response.responseText + ')');
if (res != null)
this.serverdata['system-info'] = res;
if (this.serverdata['system-info'] == null)
window.setTimeout(this.loadSystemInfo, 1000);
},
error: function() {
if (this.serverdata['system-info'] == null)
window.setTimeout(this.loadSystemInfo, 1000);
}
});
}
},
reconnectNow: function() {
if (this.lostConnectionCountDownHelper.isRunning()) {
this.lostConnectionCountDownHelper.stop(true);
}
},
updateCurrentState: function(force) {
if (this.updateRequestRunning && !force)
return;
var params = force ? { action: 'get-current-state' } : this.updateRequestParams;
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,
params: params,
timeout: timeout,
scope: this,
success: function(response) {
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;
this.updateRequestParams.lasteventid = res.LastEventID;
//Register next request
if (!force)
{
this.updateRequestRunning = false;
this.updateCurrentState();
}
if (realUpdate)
this.fireEvent('current-state-updated', this.serverdata['current-state']);
if (this.getExpectedPauseEnd() != null)
this.pauseCountDownHelper.start(this.getExpectedPauseEnd());
else if (this.pauseCountDownHelper.isRunning())
this.pauseCountDownHelper.stop(true);
}
},
failure: function(response, opts) {
//Register next request
if (!force)
{
Ext.log('Failure in longpoll: ' + response.status + ', timeout: ' + response.timedout);
this.updateRequestFailureCount++;
this.updateRequestRunning = false;
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();
}
}
}
});
},
getExpectedPauseEnd: function() {
var pauseEnd = this.serverdata['current-state'].EstimatedPauseEnd;
if (pauseEnd != null) {
pauseEnd = Duplicati.Utility.parseJsonDate(pauseEnd);
if (pauseEnd != null && pauseEnd.getTime() > new Date().getTime())
return pauseEnd;
}
return null;
},
getSchedulePosition: function(id) {
var state = this.serverdata['current-state'];
if (state == null)
return -1;
if (id == state.ActiveScheduleId)
return 0;
else if (state.SchedulerQueueIds != null)
for(var i = 0; i < state.SchedulerQueueIds.length; i++)
if (state.SchedulerQueueIds[i] == id)
return i+1;
return -1;
},
pause: function(duration) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: {
action: 'send-command',
command: 'pause',
duration: duration
},
success: function(response) { }
});
},
resume: function() {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: {
action: 'send-command',
command: 'resume'
},
success: function(response) { }
});
},
isPaused: function() {
var state = this.serverdata['current-state'];
if (state != null)
return state.ProgramState != 'Running';
return true;
},
togglePause: function() {
if (this.isPaused())
this.resume();
else
this.pause();
},
getInstalledCompressionModules: function(callback) {
if (this.serverdata['installed-compression-modules'] == null) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: { action: 'list-installed-compression-modules' },
success: function(response) {
self.serverdata['installed-compression-modules'] = eval('(' + response.responseText + ')');
callback(self.serverdata['installed-compression-modules']);
}
});
} else {
callback(this.serverdata['installed-compression-modules']);
}
},
getInstalledGenericModules: function(callback) {
if (this.serverdata['installed-generic-modules'] == null) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: { action: 'list-installed-generic-modules' },
success: function(response) {
self.serverdata['installed-generic-modules'] = eval('(' + response.responseText + ')');
callback(self.serverdata['installed-generic-modules']);
}
});
} else {
callback(this.serverdata['installed-generic-modules']);
}
},
getInstalledEncryptionModules: function(callback) {
if (this.serverdata['installed-encryption-modules'] == null) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: { action: 'list-installed-encryption-modules' },
success: function(response) {
self.serverdata['installed-encryption-modules'] = eval('(' + response.responseText + ')');
callback(self.serverdata['installed-encryption-modules']);
}
});
} else {
callback(this.serverdata['installed-encryption-modules']);
}
},
getBackupDefaults: function(callback) {
if (this.serverdata['backup-defaults'] == null) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: { action: 'get-backup-defaults' },
success: function(response) {
self.serverdata['backup-defaults'] = eval('(' + response.responseText + ')');
callback(self.serverdata['backup-defaults']);
},
scope: this
});
} else {
callback(this.serverdata['backup-defaults']);
}
},
runBackup: function(id, full) {
var self = this;
Ext.Ajax.request({
url: this.controlUrl,
params: {
action: 'send-command',
command: 'run-backup',
id: id,
full: full
},
success: function(response) {
}
});
}
});
@@ -1,168 +0,0 @@
Ext.define('Duplicati.Utility', {
statics: {
strings: {
terabyteShort: 'TB',
gigabyteShort: 'GB',
megabyteShort: 'MB',
kilobyteShort: 'KB',
bytesShort: 'bytes',
prefixAgo: null,
prefixFromNow: "in",
suffixAgo: "ago",
suffixFromNow: null,
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
wordSeparator: " "
},
timeAgoTimer: window.setInterval('Duplicati.Utility.updateTimeAgoFields()', 1000 * 150),
//Simplified version of jquery.timeago
timeAgo: function(date) {
var distanceMillis = (new Date().getTime() - date.getTime());
var strings = this.strings;
var prefix = strings.prefixAgo;
var suffix = strings.suffixAgo;
if (distanceMillis < 0) {
prefix = strings.prefixFromNow;
suffix = strings.suffixFromNow;
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
var words = seconds < 45 && strings.seconds.replace(/%d/i, Math.round(seconds)) ||
seconds < 90 && strings.minute ||
minutes < 45 && strings.minutes.replace(/%d/i, Math.round(minutes)) ||
minutes < 90 && strings.hour ||
hours < 24 && strings.hours.replace(/%d/i, Math.round(hours)) ||
hours < 42 && strings.day ||
days < 30 && strings.days.replace(/%d/i, Math.round(days)) ||
days < 45 && strings.month ||
days < 365 && strings.months.replace(/%d/i, Math.round(days / 30)) ||
years < 1.5 && strings.year ||
strings.years.replace(/%d/i, Math.round(years));
var separator = strings.wordSeparator === undefined ? " " : strings.wordSeparator;
return Ext.String.trim([prefix, words, suffix].join(separator));
},
updateTimeAgoFields: function() {
var parent = Ext.get(document);
var els = parent.query('.marker-time-ago');
for(var i = 0; i < els.length; i++) {
var time = this.parseJsonDate(els[i].title);
if (els[i].nextSibling.nodeType == 3)
els[i].nextSibling.nodeValue = this.timeAgo(time);
else if (els[i].nextSibling.innerText != null)
els[i].nextSibling.innerText = this.timeAgo(time);
}
},
parseJsonDate: function(str) {
if (str == null)
return null;
if (Ext.String.trim(str).length == 0)
return null;
if (str.indexOf("\/") == 0)
{
var strtmp = str.replace(/\/Date\((-?\d+(((\+|\-)\d+)|Z|z)?)\)\//gi, "new Date($1)");
return eval(strtmp);
}
else
{
return new Date(str);
}
},
formatSecondsAsTime: function(seconds) {
seconds = parseInt(seconds);
var hours = parseInt(Math.floor(seconds / (60 * 60)));
seconds = seconds - (hours * 60 * 60);
var minutes = parseInt(Math.floor(seconds / 60));
seconds = seconds - (minutes * 60);
var res = '';
if (hours > 0) {
res += hours + ':';
if (minutes < 10)
res += '0';
}
res += minutes + ':' ;
if (seconds < 10)
res += '0';
res += seconds;
return res;
},
formatSizeString: function(size) {
size = parseInt(size);
if (isNaN(size))
return size;
var strings = this.strings;
if (size >= 1024 * 1024 * 1024 * 1024)
return (size / (1024 * 1024 * 1024 * 1024.0)).toFixed(2) + ' ' + strings.terabyteShort;
else if (size >= 1024 * 1024 * 1024)
return (size / (1024 * 1024 * 1024.0)).toFixed(2) + ' ' + strings.gigabyteShort;
else if (size >= 1024 * 1024)
return (size / (1024 * 1024.0)).toFixed(2) + ' ' + strings.megabyteShort;
else if (size >= 1024)
return (size / (1024.0)).toFixed(2) + ' ' + strings.kilobyteShort;
else
return size + ' ' + strings.bytesShort;
},
estimatedFreeSpace: function(assignedQuota, freeQuota, backupSize) {
if (assignedQuota != null && freeQuota != null && backupSize != null)
return Math.min(parseInt(assignedQuota) - parseInt(backupSize), parseInt(freeQuota));
else if (assignedQuota != null && backupSize != null)
return parseInt(assignedQuota) - parseInt(backupSize);
else if (freeQuota != null)
return parseInt(freeQuota);
else
return null;
},
createRecordFromData: function(classname, data) {
var entry = Ext.create(classname);
var model = Ext.ModelManager.getModel(classname);
var fields = model.getFields();
var associations = entry.associations;
for(var i = 0; i < fields.length; i++) {
var key = fields[i].mapping || fields[i].name;
if (data[key] !== undefined)
entry.set(fields[i].name, data[key]);
}
for(var i = 0; i < associations.length; i++) {
var a = associations.getAt(i);
if (data[a.associationKey])
entry[a.setterName](Duplicati.Utility.createRecordFromData(a.associatedName, data[a.associationKey]));
}
return entry;
}
}
});
@@ -1,168 +0,0 @@
Ext.define('Duplicati.controller.BackupConfig', {
extend: 'Ext.app.Controller',
onBtnGeneratePasswordClick: function(button, e, options) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.,_:;+#?=)(/&%$§";
for( var i=0; i < 16; i++ ) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
var t = Ext.getCmp('sEncryptionPassword');
var t2 = Ext.getCmp('sEncryptionPasswordCheck');
var pwdButton = Ext.getCmp('btnPassword');
t.inputEl.dom.type = t2.inputEl.dom.type = 'text';
pwdButton.setText( 'Hide Password' );
t.setValue(text);
},
onButtonClick: function(button, e, options) {
var t = Ext.getCmp('sEncryptionPassword');
var t2 = Ext.getCmp('sEncryptionPasswordCheck');
var pwdButton = Ext.getCmp('btnPassword');
t.inputEl.dom.type = t2.inputEl.dom.type = ( t.inputEl.dom.type == 'password' )?'text':'password';
pwdButton.setText( ( t.inputEl.dom.type == 'password' )?'Show Password':'Hide Password' );
},
onTAddLocationClick: function(tool, e, options) {
Ext.create('Duplicati.view.wndAddLocation').show();
},
onTAddFilterClick: function(tool, e, options) {
Ext.create('Duplicati.view.wndAddFilter').show();
},
onBtnBuildURLClick: function(button, e, options) {
Ext.create('Duplicati.view.wndCreateConnection').show();
},
onTAddOverrideClick: function(tool, e, options) {
Ext.create('Duplicati.view.wndAddOverride').show();
},
onBtnNextClick: function(button, e, options) {
if( Ext.getCmp('btnNext').getText() == 'Finish' ) {
// Save all the stuff and Finish work
// Checks need to happen here, if everything is filled in proper
alert( "DONE!!");
button.findParentByType('window').destroy();
} else {
var wizardTabs = Ext.getCmp('panelWizard');
wizardTabs.setActiveTab( wizardTabs.getActiveTab().activeItem + 1 );
}
},
onAddLocationsClick: function(button, e, options) {
var records = Ext.getCmp('treeLocation').getChecked();
Ext.getCmp('Locations').getStore().removeAll();
Ext.Array.each(records, function(rec){
Ext.getCmp('Locations').getStore().add(
new Duplicati.model.TaskItems.BackupLocation ( {
Location: rec.get('id'),
TotalSize:0
}
)
);
});
Ext.getCmp("winAddLocation").destroy();
},
onBtnCloseClick: function(button, e, options) {
button.findParentByType('window').destroy();
},
afterWindowLayout: function(abstractcontainer, layout, options) {
if (abstractcontainer.scheduleId == null || abstractcontainer.scheduleId < 0)
{
Duplicati.service.getBackupDefaults(function(data) {
var entry = Duplicati.Utility.createRecordFromData('Duplicati.model.BackupJob', data.data);
abstractcontainer.loadRecord(entry);
});
}
else
{
var backupJobModel = Ext.ModelManager.getModel('Duplicati.model.BackupJob');
backupJobModel.load(abstractcontainer.scheduleId, {
scope: this,
success : function(backupJobResult, operation) {
abstractcontainer.loadRecord(backupJobResult);
}
});
}
},
onControllerClickStub: function() {
},
onWizardTabChange: function(tabPanel, newCard, oldCard, eOpts) {
if (newCard.activeItem == -1) {
Ext.getCmp('btnNext').setText( 'Finish' );
} else {
Ext.getCmp('btnNext').setText( 'Next >' );
}
},
afterEncryptionModuleChange: function() {
var combo = Ext.getCmp('EncryptionModule');
var t = Ext.getCmp('sEncryptionPassword');
var t2 = Ext.getCmp('sEncryptionPasswordCheck');
var b = Ext.getCmp('btnPassword');
var b2 = Ext.getCmp('btnGeneratePassword');
if (combo.getValue() == '') {
t.disable();
t2.disable();
b.disable();
b2.disable();
} else {
t.enable();
t2.enable();
b.enable();
b2.enable();
}
},
init: function() {
this.control({
"#btnGeneratePassword": {
click: this.onBtnGeneratePasswordClick
},
"#btnPassword": {
click: this.onButtonClick
},
"#tAddLocation": {
click: this.onTAddLocationClick
},
"#tAddFilter": {
click: this.onTAddFilterClick
},
"#tAddOverride": {
click: this.onTAddOverrideClick
},
"#btnBuildURL": {
click: this.onBtnBuildURLClick
},
"#btnNext": {
click: this.onBtnNextClick
},
"#btnAddLocations": {
click: this.onAddLocationsClick
},
"#btnClose": {
click: this.onBtnCloseClick
},
"backupconfigpanel": {
afterlayout: this.afterWindowLayout
},
"#EncryptionModule": {
change: this.afterEncryptionModuleChange
},
"#panelWizard": {
tabchange: this.onWizardTabChange
}
});
}
});
@@ -1,36 +0,0 @@
Ext.define('Duplicati.controller.Schedules', {
extend: 'Ext.app.Controller',
stores: [ 'Schedules' ],
views: [ 'schedule.List' ],
refs: [{
selector: 'viewport > panel',
ref: 'basicPanel'
}],
lastEventID: -1,
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
this.application.on({
'current-state-updated': function(data) {
//Update the data store if there is new metadata
if (data.LastEventID != this.lastEventID)
this.getSchedulesStore().load();
this.lastEventID = data.LastEventID;
},
scope: this
});
},
onPanelRendered: function() {
//console.log('The panel was rendered');
}
});
@@ -1,16 +0,0 @@
Ext.define('Duplicati.controller.StatuswindowFooter', {
extend: 'Ext.app.Controller',
views: [ 'StatuswindowFooter' ],
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
//console.log('The footer panel was rendered');
}
});
@@ -1,60 +0,0 @@
Ext.define('Duplicati.controller.StatuswindowHeader', {
extend: 'Ext.app.Controller',
views: [ 'StatuswindowHeader' ],
refs: [{
selector: '#status-window-header-pause-button',
ref: 'pauseButton'
}, {
selector: '#status-window-header-pause-menu',
ref: 'pauseMenu'
}],
init: function() {
this.application.on({
'current-state-updated': function() {
var btn = this.getPauseButton();
var mnu = this.getPauseMenu();
var srv = this.application.service;
var util = Duplicati.Utility;
if (srv.isPaused()) {
if (srv.getExpectedPauseEnd() != null)
btn.setText('Resume (' + util.formatSecondsAsTime((srv.getExpectedPauseEnd().getTime() - new Date().getTime()) / 1000) + ')');
else
btn.setText('Resume');
btn.setIconCls('backups-paused');
mnu.setText('Resume Duplicati');
} else {
btn.setText('Pause');
btn.setIconCls('backups-running');
mnu.setText('Pause Duplicati');
}
},
scope: this
});
this.application.on({
'count-down-pause-timer': function(data) {
var btn = this.getPauseButton();
var srv = this.application.service;
var util = Duplicati.Utility;
if (data <= 0)
btn.setText('Pause');
else
btn.setText('Resume (' + util.formatSecondsAsTime(data) + ')');
},
scope: this
});
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
//console.log('The header panel was rendered');
}
});
@@ -1,35 +0,0 @@
Ext.define('Duplicati.model.BackupJob', {
extend: 'Ext.data.Model',
uses: [
'Duplicati.model.Task',
'Duplicati.model.Schedule'
],
proxy: {
type: 'ajax',
url: '/control.cgi?action=get-schedule-details',
reader: {
type: 'json',
idProperty: 'ID',
root: 'data'
}
},
associations: [{
name: 'task',
type: 'hasOne',
associationKey: 'Task',
primaryKey: 'ID',
getterName: 'getTask',
setterName: 'setTask',
model: 'Duplicati.model.Task'
},{
name: 'schedule',
type: 'hasOne',
associationKey: 'Schedule',
primaryKey: 'ID',
getterName: 'getSchedule',
setterName: 'setSchedule',
model: 'Duplicati.model.Schedule'
}]
});
@@ -1,41 +0,0 @@
Ext.define('Duplicati.model.Schedule', {
extend: 'Ext.data.Model',
associations: [{
name: 'task',
type: 'hasOne',
model: 'Duplicati.model.Task',
primaryKey: 'ID',
foreignKey: 'ScheduleID'
}],
fields: [
{
name: 'NextScheduledTime'
},
{
name: 'AllowedWeekdays'
},
{
name: 'ID'
},
{
name: 'Name'
},
{
name: 'Path'
},
{
name: 'When'
},
{
name: 'Repeat'
},
{
name: 'Weekdays'
},
{
name: 'Metadata'
}
]
});
@@ -1,73 +0,0 @@
Ext.define('Duplicati.model.ScheduleItems.Metadata', {
extend: 'Ext.data.Model',
fields: [
{
name: 'total_size',
mapping: 'total-size'
},
{
name: 'full_backup_count'
},
{
name: 'total_volume_count'
},
{
name: 'total_file_count'
},
{
name: 'longest_chain_length'
},
{
name: 'current_chain_length'
},
{
name: 'current_full_date'
},
{
name: 'current_chain_size'
},
{
name: 'last_backup_date'
},
{
name: 'last_backup_size'
},
{
name: 'total_backup_size'
},
{
name: 'total_quota_space'
},
{
name: 'free_quota_space'
},
{
name: 'source_file_size'
},
{
name: 'source_file_count'
},
{
name: 'source_folder_count'
},
{
name: 'orphan_file_count'
},
{
name: 'orphan_file_size'
},
{
name: 'alien_file_count'
},
{
name: 'alien_file_size'
},
{
name: 'total_backup_sets'
},
{
name: 'last_backup_completed_time'
}
]
});
@@ -1,88 +0,0 @@
Ext.define('Duplicati.model.Task', {
extend: 'Ext.data.Model',
uses: [
'Duplicati.model.TaskItems.BackendSettings',
'Duplicati.model.TaskItems.Extensions',
'Duplicati.model.TaskItems.Overrides',
'Duplicati.model.TaskItems.EncryptionSettings',
'Duplicati.model.TaskItems.CompressionSettings'
],
associations: [{
name: 'backendSettings',
associationKey: 'BackendSettings',
type: 'hasOne',
model: 'Duplicati.model.TaskItems.BackendSettings',
getterName: 'getBackendSettings',
setterName: 'setBackendSettings'
},{
name: 'extensions',
associationKey: 'Extensions',
type: 'hasOne',
model: 'Duplicati.model.TaskItems.Extensions',
getterName: 'getExtensions',
setterName: 'setExtensions'
},{
name: 'overrides',
associationKey: 'Overrides',
type: 'hasOne',
model: 'Duplicati.model.TaskItems.Overrides',
getterName: 'getOverrides',
setterName: 'setOverrides'
},{
name: 'encryptionSettings',
associationKey: 'EncryptionSettings',
type: 'hasOne',
model: 'Duplicati.model.TaskItems.EncryptionSettings',
getterName: 'getEncryptionSettings',
setterName: 'setEncryptionSettings'
},{
name: 'compressionSettings',
associationKey: 'CompressionSettings',
type: 'hasOne',
model: 'Duplicati.model.TaskItems.CompressionSettings',
getterName: 'getCompressionSettings',
setterName: 'setCompressionSettings'
}],
fields: [
{
name: 'Filter'
},
{
name: 'ID'
},
{
name: 'Service'
},
{
name: 'Encryptionkey'
},
{
name: 'SourcePath'
},
{
name: 'ScheduleID'
},
{
name: 'KeepFull'
},
{
name: 'KeepTime'
},
{
name: 'FullAfter'
},
{
name: 'IncludeSetup',
type: 'boolean'
},
{
name: 'EncryptionModule'
},
{
name: 'CompressionModule'
}
]
});
@@ -1,18 +0,0 @@
Ext.define('Duplicati.model.TaskItems.BackendSettings', {
extend: 'Ext.data.Model',
fields: [
{
name: 'UI_Checked_empty'
},
{
name: 'Destination'
},
{
name: 'Username'
},
{
name: 'Password'
}
]
});
@@ -1,14 +0,0 @@
Ext.define('Duplicati.model.TaskItems.BackupLocation', {
extend: 'Ext.data.Model',
fields: [
{
name: 'Location',
type: 'string'
},
{
name: 'TotalSize',
type: 'float'
}
]
});
@@ -1,3 +0,0 @@
Ext.define('Duplicati.model.TaskItems.CompressionSettings', {
extend: 'Ext.data.Model'
});
@@ -1,3 +0,0 @@
Ext.define('Duplicati.model.TaskItems.EncryptionSettings', {
extend: 'Ext.data.Model'
});
@@ -1,120 +0,0 @@
Ext.define('Duplicati.model.TaskItems.Extensions', {
extend: 'Ext.data.Model',
fields: [
{
name: 'UploadBandwidth',
mapping: "Upload Bandwidth"
},
{
name: 'DownloadBandwidth',
mapping: 'Download Bandwidth'
},
{
name: 'MaxUploadSize',
mapping: 'Max Upload Size'
},
{
name: 'VolumeSize',
mapping: 'Volume Size'
},
{
name: 'ThreadPriority',
mapping: 'Thread Priority'
},
{
name: 'AsyncTransfer',
mapping: 'Async Transfer',
type: 'boolean',
convert: parseBool
},
{
name: 'IgnoreTimestamps',
mapping: 'Ignore Timestamps',
type: 'boolean',
convert: parseBool
},
{
name: 'FileSizeLimit',
mapping: 'File Size Limit'
},
{
name: 'DisableAESfallbackencryption',
mapping: 'Disable AES fallback encryption',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesVersion',
mapping: 'Select Files - Version',
type: 'int',
convert: parseInt
},
{
name: 'SelectFilesUseSimpleMode',
mapping: 'Select Files - Use Simple Mode',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesIncludeDocuments',
mapping: 'Select Files - Include Documents',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesIncludeDesktop',
mapping: 'Select Files - Include Desktop',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesIncludeMusic',
mapping: 'Select Files - Include Music',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesIncludeImages',
mapping: 'Select Files - Include Images',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectFilesIncludeAppData',
mapping: 'Select Files - Include AppData',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectWhenWarnedNoSchedule',
mapping: 'Select When - Warned No Schedule',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectWhenWarnedTooManyIncrementals',
mapping: 'Select When - Warned Too Many Incrementals',
type: 'boolean',
convert: parseBool
},
{
name: 'SelectWhenWarnedNoIncrementals',
mapping: 'Select When - Warned No Incrementals',
type: 'boolean',
convert: parseBool
},
{
name: 'PasswordSettingsWarnedNoPassword',
mapping: 'Password Settings - Warned No Password',
type: 'boolean',
convert: parseBool
},
{
name: 'CleanupSettingsWarnedNoCleanup',
mapping: 'Cleanup Settings - Warned No Cleanup',
type: 'boolean',
convert: parseBool
}
]
});
@@ -1,3 +0,0 @@
Ext.define('Duplicati.model.TaskItems.Overrides', {
extend: 'Ext.data.Model'
});
@@ -1,38 +0,0 @@
Ext.define('Duplicati.model.override.BackupJob', {
requires: 'Duplicati.model.BackupJob'
}, function() {
Ext.override(Duplicati.model.BackupJob, {
setValues: function(values, arrayField) {
var me = this;
function setVal(fieldId, val) {
if (arrayField) {
fieldId = arrayField + '.' + fieldId;
}
var field = me.findField(fieldId);
if (field) {
field.setValue(val);
if (me.trackResetOnLoad) {
field.resetOriginalValue();
}
} else if(Ext.isObject(val)) {
me.setValues(val, fieldId);
}
}
alert( "Servus setValues" );
if (Ext.isArray(values)) {
// array of objects
Ext.each(values, function(val) {
setVal(val.id, val.value);
});
} else {
// object hash
Ext.iterate(values, setVal);
}
return this;
}
});
});
@@ -1,23 +0,0 @@
Ext.define('Duplicati.store.AdditionalPathStore', {
extend: 'Ext.data.Store',
requires: [
'Duplicati.model.TaskItems.BackupLocation'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: true,
storeId: 'pathStore',
model: 'Duplicati.model.TaskItems.BackupLocation',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'root'
}
}
}, cfg)]);
}
});
@@ -1,24 +0,0 @@
Ext.define('Duplicati.store.BackupJob', {
extend: 'Ext.data.Store',
requires: [
'Duplicati.model.BackupJob'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'MyJsonStore',
model: 'Duplicati.model.BackupJob',
proxy: {
type: 'ajax',
url: '/control.cgi?action=get-schedule-details',
reader: {
type: 'json',
idProperty: 'ID',
root: 'data'
}
}
}, cfg)]);
}
});
@@ -1,26 +0,0 @@
Ext.define('Duplicati.store.DefaultSizeRangeStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'DefaultSizeRangeStore',
data: [
{key: 'b', value: 'bytes'},
{key: 'kb', value: 'Kilobytes'},
{key: 'mb', value: 'Megabytes'},
{key: 'gb', value: 'Gigabytes'},
{key: 'tb', value: 'Terabyts'}
],
fields: [
{
name: 'key'
},
{
name: 'value'
}
]
}, cfg)]);
}
});
@@ -1,28 +0,0 @@
Ext.define('Duplicati.store.DefaultTimeRangesStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'DefaultTimeRangesStore',
data: [
{key: 's', value: 'Seconds'},
{key: 'm', value: 'Minutes'},
{key: 'h', value: 'Hours'},
{key: 'D', value: 'Days'},
{key: 'W', value: 'Weeks'},
{key: 'M', value: 'Months'},
{key: 'Y', value: 'Years'}
],
fields: [
{
name: 'key'
},
{
name: 'value'
}
]
}, cfg)]);
}
});
@@ -1,24 +0,0 @@
Ext.define('Duplicati.store.DeleteOldChainsWhenStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'DeleteOldChainsWhenStore',
data: [
{key: '0', value: 'When there are more chains than ...'},
{key: '1', value: 'When the last backup in the chain is older than ...'},
{key: '2', value: 'Never'}
],
fields: [
{
name: 'key'
},
{
name: 'value'
}
]
}, cfg)]);
}
});
@@ -1,44 +0,0 @@
Ext.define('Duplicati.store.EncryptionMethodStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: true,
filterOnLoad: false,
sortOnLoad: false,
storeId: 'EncryptionMethodStore',
/*listeners: {
load: function(records, success, eOpts) {
alert('WS');
}
//TODO: Should we add the empty row here instad?
},*/
fields: [
{
mapping: 'DisplayName',
name: 'encryptionMethodName',
type: 'string'
},
{
mapping: 'FilenameExtension',
name: 'encryptionMethodIdentifier',
type: 'string'
}
],
proxy: {
type: 'ajax',
url: '/control.cgi?action=list-installed-encryption-modules',
reader: {
type: 'array',
idProperty: 'id'
}
}
}, cfg)]);
}
});
@@ -1,21 +0,0 @@
Ext.define('Duplicati.store.LabelStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'LabelStore',
data: [
{name: 'private'},
{name: 'important'},
{name: 'weekly'}
],
fields: [
{
name: 'name'
}
]
}, cfg)]);
}
});
@@ -1,37 +0,0 @@
Ext.define('Duplicati.store.MyComputerTreeStore', {
extend: 'Ext.data.TreeStore',
constructor: function(cfg) {
cfg = cfg || {};
this.callParent([Ext.apply({
autoLoad: true,
filterOnLoad: false,
sortOnLoad: false,
storeId: 'MyComputerTreeStore',
folderSort: false,
nodeParam: 'path',
root: {
text: 'My Computer',
id: '/',
expanded: false
},
proxy: {
type: 'ajax',
url: '/control.cgi?action=get-folder-contents&onlyfolders=true',
reader: {
type: 'json',
root: '/'
}
},
fields: [
{
mapping: 'check',
name: 'checked'
},
{
name: 'text'
}
]
}, cfg)]);
}
});
@@ -1,25 +0,0 @@
Ext.define('Duplicati.store.NewBackupChainWhenStore', {
extend: 'Ext.data.Store',
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'NewBackupChainWhenStore',
data: [
{key: '0', value: 'When there are more backups in the chain than ...'},
{key: '1', value: 'When the chain is older than ...'},
{key: '2', value: 'Once, and then backup changes only'},
{key: '3', value: 'Every time'}
],
fields: [
{
name: 'key'
},
{
name: 'value'
}
]
}, cfg)]);
}
});
@@ -1,95 +0,0 @@
Ext.define('Duplicati.store.Schedules', {
extend: 'Ext.data.Store',
model: 'Duplicati.model.Schedule',
autoLoad: true,
/* Sort order,
* first by queue position
* second by next schedule time,
* third by last backup time
* */
sorters: [{
sorterFn: function(a, b) {
var schedulePosA = Duplicati.service.getSchedulePosition(a.get("ID"));
var schedulePosB = Duplicati.service.getSchedulePosition(b.get("ID"));
if(schedulePosA >= 0 && schedulePosB >= 0)
{
if (schedulePosA == schedulePosB)
return 0;
else
return schedulePosA < schedulePosB ? -1 : 1;
}
else if (schedulePosA >= 0)
return -1;
else if (schedulePosB >= 0)
return 1;
else
return 0;
}
}, {
sorterFn: function(a, b) {
var nextTimeA = Duplicati.Utility.parseJsonDate(a.get('NextScheduledTime'));
var nextTimeB = Duplicati.Utility.parseJsonDate(b.get('NextScheduledTime'));
var now = new Date().getTime();
//Scheduled time in past, but not in queue, so it will not run
if (nextTimeA != null && nextTimeA < now)
nextTimeA = null;
if (nextTimeB != null && nextTimeB < now)
nextTimeB = null;
if (nextTimeA != null && nextTimeB != null)
{
nextTimeA = nextTimeA.getTime();
nextTimeB = nextTimeB.getTime();
if (nextTimeA == nextTimeB)
return 0;
else
return nextTimeA < nextTimeB ? -1 : 1;
}
else if (nextTimeA != null)
return -1;
else if (nextTimeB != null)
return 1;
else
return 0;
}
}, {
sorterFn: function(a, b) {
var lastTimeA = Duplicati.Utility.parseJsonDate(a.data.Metadata['last-backup-completed-time']);
var lastTimeB = Duplicati.Utility.parseJsonDate(b.data.Metadata['last-backup-completed-time']);
if (lastTimeA == null)
lastTimeA = Duplicati.Utility.parseJsonDate(a.data.Metadata['last-backup-date']);
if (lastTimeB == null)
lastTimeB = Duplicati.Utility.parseJsonDate(b.data.Metadata['last-backup-date']);
if ((lastTimeA != null && lastTimeB != null))
{
lastTimeA = lastTimeA.getTime();
lastTimeB = lastTimeB.getTime();
if (lastTimeA == lastTimeB)
return 0;
else
return lastTimeA > lastTimeB ? -1 : 1;
}
else if (lastTimeA != null)
return -1;
else if (lastTimeB != null)
return 1;
else
return 0;
}
}, {
property: 'Name'
}],
proxy: {
type: 'ajax',
url: 'control.cgi?action=list-schedules',
reader: {
type: 'json'
}
}
});
@@ -1,32 +0,0 @@
Ext.define('Duplicati.view.AboutWindow', {
statics: {
dialogWindow: null,
show: function() {
if (this.dialogWindow == null)
this.dialogWindow = Ext.create('Ext.window.Window', {
title: 'About Duplicati',
height: 200,
width: 400,
modal: true,
resizable: false,
buttonAlign: 'center',
closeAction: 'hide',
layout: 'auto',
items: [{
xtype: 'label',
text: 'Duplicati 2.0'
}],
buttons: [{
xtype: 'button',
text: 'OK',
handler: function() {
Duplicati.view.AboutWindow.dialogWindow.hide();
}
}]
});
this.dialogWindow.show();
}
}
});
@@ -1,927 +0,0 @@
Ext.define('Duplicati.view.BackupConfig', {
extend: 'Ext.form.Panel',
xtype: 'backupconfigpanel',
draggable: false,
floating: false,
frame: false,
height: 550,
width: 698,
autoScroll: false,
resizable: false,
layout: {
type: 'absolute'
},
bodyBorder: false,
closable: false,
collapsed: false,
collapsible: false,
frameHeader: false,
hideCollapseTool: false,
overlapHeader: false,
preventHeader: true,
title: 'Backup Job',
titleCollapse: true,
waitMsgTarget: true,
initComponent: function(params) {
var me = this;
me.scheduleId = me.initialConfig.scheduleId;
me.initialConfig = Ext.apply({
waitMsgTarget: true
}, me.initialConfig);
Ext.applyIf(me, {
items: [
{
xtype: 'tabpanel',
height: 484,
id: 'panelWizard',
activeTab: 0,
plain: true,
layout: {
deferredRender: true,
type: 'card'
},
items: [
{
xtype: 'panel',
height: 409,
activeItem: 0,
layout: {
type: 'anchor'
},
hideCollapseTool: false,
title: 'General',
items: [
{
xtype: 'fieldset',
margin: 10,
padding: 10,
collapsed: false,
collapsible: false,
title: 'Name & Label',
formBind: false,
items: [
{
xtype: 'textfield',
id: 'Name',
name: 'Schedule.Name',
fieldLabel: 'Name of Backup',
labelAlign: 'right',
labelWidth: 140,
msgTarget: 'side',
allowBlank: false,
blankText: 'Required: Short Description to identify your Backup',
disableKeyFilter: false,
emptyText: 'Short Description to identify your Backup',
enableKeyEvents: false,
minLength: 6,
anchor: '100%',
formBind: false
},
{
xtype: 'combobox',
id: 'sLabel',
name: 'Schedule.Path',
fieldLabel: 'Labels/Groups',
labelAlign: 'right',
labelWidth: 140,
msgTarget: 'side',
blankText: 'Required: Select a Label or Create a new one',
emptyText: 'Select a Label or Create a new one',
displayField: 'name',
multiSelect: true,
store: 'LabelStore',
anchor: '100%',
formBind: false,
listeners: {
change: {
fn: me.onSLabelChange,
scope: me
}
}
},
{
xtype: 'container',
height: 27,
hidden: true,
layout: {
align: 'stretchmax',
pack: 'end',
type: 'hbox'
},
items: [
{
xtype: 'button',
text: 'Manage Labels',
flex: 1
}
]
}
]
},
{
xtype: 'fieldset',
height: 220,
hidden: false,
margin: 10,
padding: 10,
styleHtmlContent: false,
activeItem: 0,
title: 'Security',
formBind: false,
items: [
{
xtype: 'component',
floating: false,
html: 'It is recommended to encrypt all backups which are stored on remote Servers',
margin: 10,
padding: 10,
tpl: [
'<h1>sepp</h1>'
],
autoScroll: false
},
{
xtype: 'combobox',
id: 'EncryptionModule',
name: 'Task.EncryptionModule',
fieldLabel: 'Encryption method',
labelAlign: 'right',
labelWidth: 140,
editable: false,
forceSelection: true,
queryParam: 'encryptionMethodName',
store: 'EncryptionMethodStore',
displayField: 'encryptionMethodName',
valueField: 'encryptionMethodIdentifier',
anchor: '100%',
formBind: false,
queryMode: 'local'
},
{
xtype: 'textfield',
disabled: false,
id: 'sEncryptionPassword',
stateful: false,
inputType: 'password',
name: 'sEncryptionPassword',
fieldLabel: 'Encryption Password',
labelAlign: 'right',
labelWidth: 140,
msgTarget: 'side',
disableKeyFilter: false,
minLength: 6,
anchor: '100%',
formBind: false
},
{
xtype: 'textfield',
validator: function(value) {
var password1 = Ext.getCmp('sEncryptionPassword');
return (value === password1.getValue() || value.length < 6) ? true : 'Passwords do not match.';
},
id: 'sEncryptionPasswordCheck',
stateful: false,
maintainFlex: false,
inputType: 'password',
name: 'sEncryptionPasswordCheck',
readOnly: false,
fieldLabel: 'Repeat Password',
labelAlign: 'right',
labelWidth: 140,
minLength: 6,
anchor: '100%',
formBind: false
},
{
xtype: 'button',
id: 'btnGeneratePassword',
style: 'float:right',
autoWidth: true,
scale: 'medium',
text: 'Generate Password',
formBind: false
},
{
xtype: 'button',
id: 'btnPassword',
style: 'float:right',
autoWidth: true,
repeat: false,
scale: 'medium',
text: 'Show Password',
formBind: false
}
]
}
]
},
{
xtype: 'panel',
height: 367,
activeItem: 1,
title: 'Source Data',
items: [
{
xtype: 'fieldset',
margin: 10,
padding: 10,
title: 'Standard Locations',
items: [
{
xtype: 'checkboxgroup',
id: 'chkgStandardLocations',
margin: '',
width: 400,
fieldLabel: '',
columns: 1,
vertical: true,
name: 'Files',
items: [
{
xtype: 'checkboxfield',
id: 'chkMyDocuments',
name: 'Task.Extensions.SelectFilesIncludeDocuments',
hideLabel: false,
labelPad: 10,
boxLabel: 'My Documents'
},
{
xtype: 'checkboxfield',
id: 'chkMyMusic',
name: 'Task.Extensions.SelectFilesIncludeMusic',
boxLabel: 'My Music'
},
{
xtype: 'checkboxfield',
id: 'chkMyVideos',
name: 'Task.Extensions.SelectFilesIncludeMyVideos',
boxLabel: 'My Videos'
},
{
xtype: 'checkboxfield',
id: 'chkMyPictures',
name: 'Task.Extensions.SelectFilesIncludeImages',
boxLabel: 'My Pictures'
},
{
xtype: 'checkboxfield',
id: 'chkAppSettings',
name: 'Task.Extensions.SelectFilesIncludeAppData',
boxLabel: 'Application Settings'
}
]
}
]
},
{
xtype: 'gridpanel',
id: 'Locations',
margin: 10,
bodyBorder: false,
title: 'Additional Locations',
sortableColumns: false,
store: 'AdditionalPathStore',
columnLines: false,
tools: [
{
xtype: 'tool',
id: 'tAddLocation',
type: 'plus'
}
],
listeners: {
added: {
fn: me.onLocationsAdded,
scope: me
}
},
columns: [
{
xtype: 'gridcolumn',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
// this works only for Windows ...
// ...need to identify OS before
if( value.indexOf("/") == 0 && value.length > 2 && value[2] == ':') {
value = value.substr( 1, value.length);
value = value.replace(/\//g,"\\");
}
return value;
},
dataIndex: 'Location',
text: 'Location'
},
{
xtype: 'numbercolumn',
dataIndex: 'TotalSize',
text: 'Size'
}
]
},
{
xtype: 'gridpanel',
margin: 10,
bodyBorder: false,
title: 'Filter Rules',
forceFit: true,
hideHeaders: true,
scroll: 'none',
sortableColumns: false,
store: 'LabelStore',
columnLines: false,
columns: [
{
xtype: 'gridcolumn',
id: 'fldFilter',
margin: '',
dataIndex: 'string',
menuDisabled: false,
text: 'Filter'
}
],
tools: [
{
xtype: 'tool',
id: 'tAddFilter',
type: 'plus'
}
]
}
]
},
{
xtype: 'panel',
activeItem: 2,
closable: false,
title: 'Target',
items: [
{
xtype: 'fieldset',
frame: false,
id: 'pConnection',
margin: 10,
padding: 10,
title: 'Connection',
items: [
{
xtype: 'textfield',
id: 'sNameOfConnection',
name: 'NameOfConnection',
fieldLabel: 'Name of Connection',
labelAlign: 'right',
labelWidth: 140,
anchor: '100%'
},
{
xtype: 'fieldcontainer',
height: 27,
layout: {
align: 'stretch',
type: 'hbox'
},
combineErrors: true,
combineLabels: false,
fieldLabel: 'Label',
hideLabel: true,
msgTarget: 'side',
anchor: '100%',
formBind: false,
items: [
{
xtype: 'textfield',
floating: false,
id: 'sConnectionURL',
name: 'ConnectionURL',
fieldLabel: 'Connection URL',
labelAlign: 'right',
labelWidth: 140,
flex: 10
},
{
xtype: 'button',
id: 'btnBuildURL',
text: '...',
flex: 1,
margins: '0 0 5 5'
}
]
},
{
xtype: 'container',
padding: '0 0 0 145',
items: [
{
xtype: 'fieldset',
height: 110,
id: 'pCredentials',
margin: '',
padding: 10,
layout: {
align: 'stretchmax',
pack: 'center',
padding: 10,
type: 'vbox'
},
collapsible: false,
title: 'Credentials',
items: [
{
xtype: 'textfield',
id: 'sUsername',
maxWidth: 330,
minWidth: 330,
width: 330,
name: 'sUsername',
fieldLabel: 'Username',
labelAlign: 'right',
labelWidth: 70
},
{
xtype: 'textfield',
id: 'sPassword',
maxWidth: 330,
minWidth: 330,
width: 330,
inputType: 'password',
name: 'sPassword',
fieldLabel: 'Password',
labelAlign: 'right',
labelWidth: 70
}
]
},
{
xtype: 'button',
margin: '5 0 0 0',
text: 'Test Connection'
}
]
}
]
}
]
},
{
xtype: 'panel',
activeItem: 3,
title: 'Run & Delete',
items: [
{
xtype: 'fieldset',
id: 'fsSchedule',
margin: 10,
padding: 10,
title: 'Schedule',
items: [
{
xtype: 'checkboxfield',
id: 'chkRunRegular',
margin: '0 0 20 0',
name: 'chkRunRegular',
fieldLabel: 'Label',
hideLabel: true,
boxLabel: 'Run regulary at the specified times',
checked: true,
anchor: '100%',
listeners: {
change: {
fn: me.onChkRunRegularChange,
scope: me
}
}
},
{
xtype: 'fieldcontainer',
layout: {
align: 'stretchmax',
type: 'hbox'
},
fieldLabel: 'Label',
hideLabel: true,
items: [
{
xtype: 'timefield',
margin: '0 5 0 0',
fieldLabel: 'Next Time',
name: 'Schedule.When.Time',
labelSeparator: ' ',
flex: 5
},
{
xtype: 'datefield',
maintainFlex: false,
name: 'Schedule.When.Date',
fieldLabel: 'Label',
hideLabel: true,
flex: 3
},
{
xtype: 'container',
flex: 10
}
]
},
{
xtype: 'fieldcontainer',
layout: {
align: 'stretchmax',
type: 'hbox'
},
fieldLabel: '',
hideLabel: true,
items: [
{
xtype: 'numberfield',
margin: '0 5 0 0',
fieldLabel: 'Run again every',
name: 'Schedule.Repeat.Number',
minValue: 0,
labelSeparator: ' ',
flex: 5
},
{
xtype: 'combobox',
fieldLabel: 'Label',
hideLabel: true,
flex: 3,
name: 'Schedule.Repeat.Suffix',
store: 'DefaultTimeRangesStore',
editable: false,
forceSelection: true,
displayField: 'value',
valueField: 'key'
},
{
xtype: 'container',
flex: 10
}
]
},
{
xtype: 'fieldcontainer',
layout: {
align: 'stretchmax',
type: 'hbox'
},
fieldLabel: '',
hideLabel: true,
items: [
{
xtype: 'checkboxgroup',
width: 400,
fieldLabel: 'Allowed Days',
flex: 5,
name: 'Schedule.AllowedWeekdays',
items: [
{
xtype: 'checkboxfield',
boxLabel: 'Mon'
},
{
xtype: 'checkboxfield',
boxLabel: 'Tue'
},
{
xtype: 'checkboxfield',
boxLabel: 'Wed'
},
{
xtype: 'checkboxfield',
boxLabel: 'Thu'
},
{
xtype: 'checkboxfield',
boxLabel: 'Fri'
},
{
xtype: 'checkboxfield',
boxLabel: 'Sat'
},
{
xtype: 'checkboxfield',
boxLabel: 'Sun'
}
]
},
{
xtype: 'container',
flex: 2
}
]
}
]
},
{
xtype: 'fieldset',
margin: 10,
padding: 10,
title: 'Full or incremental',
items: [
{
xtype: 'combobox',
fieldLabel: 'Make a full backup',
labelWidth: 120,
store: 'NewBackupChainWhenStore',
displayField: 'value',
valueField: 'key',
editable: false,
forceSelection: true,
anchor: '100%'
},
{
xtype: 'fieldcontainer',
height: 27,
layout: {
align: 'stretch',
type: 'hbox'
},
fieldLabel: 'Label',
hideLabel: true,
items: [
{
xtype: 'numberfield',
hideEmptyLabel: false,
labelWidth: 120,
minValue: 0,
flex: 5,
margins: '0 5 0 0'
},
{
xtype: 'combobox',
fieldLabel: 'Label',
store: 'DefaultTimeRangesStore',
displayField: 'value',
valueField: 'key',
editable: false,
forceSelection: true,
hideLabel: true,
flex: 2
},
{
xtype: 'container',
flex: 8
}
]
}
]
},
{
xtype: 'fieldset',
margin: 10,
padding: 10,
title: 'Delete old backups',
items: [
{
xtype: 'displayfield',
margin: '0 0 10 0',
value: 'Please note: A full and its incremental backups are called a chain. Duplicati deletes entire backup chains only. A chain is deleted, when all its backups match the specified rule.',
hideEmptyLabel: false,
labelWidth: 120,
anchor: '100%'
},
{
xtype: 'combobox',
fieldLabel: 'Delete backups',
labelWidth: 120,
store: 'DeleteOldChainsWhenStore',
editable: false,
forceSelection: true,
displayField: 'value',
valueField: 'key',
anchor: '100%'
},
{
xtype: 'fieldcontainer',
height: 27,
layout: {
align: 'stretch',
type: 'hbox'
},
fieldLabel: 'Label',
hideLabel: true,
items: [
{
xtype: 'numberfield',
hideEmptyLabel: false,
labelWidth: 120,
minValue: 0,
flex: 5,
margins: '0 5 0 0'
},
{
xtype: 'combobox',
fieldLabel: 'Label',
store: 'DefaultTimeRangesStore',
displayField: 'value',
valueField: 'key',
editable: false,
forceSelection: true,
hideLabel: true,
flex: 2
},
{
xtype: 'container',
flex: 8
}
]
}
]
}
]
},
{
xtype: 'panel',
activeItem: -1,
title: 'Options',
items: [
{
xtype: 'fieldset',
margin: 10,
padding: 10,
title: 'Options',
items: [
{
xtype: 'combobox',
fieldLabel: 'Missed Backup',
anchor: '100%'
},
{
xtype: 'displayfield',
margin: '0 0 30 0 0',
value: 'When the computer or Duplicati turned off when a backup should have been made, this defines how Duplicati will handle this situation',
hideEmptyLabel: false,
hideLabel: false,
anchor: '100%'
},
{
xtype: 'fieldcontainer',
height: 27,
layout: {
align: 'stretch',
type: 'hbox'
},
fieldLabel: 'Label',
hideLabel: true,
items: [
{
xtype: 'numberfield',
fieldLabel: 'Max archive size',
name: 'Task.Extensions.VolumeSize.Number',
minValue: 0,
flex: 2,
margins: '0 5 0 0'
},
{
xtype: 'combobox',
name: 'Task.Extensions.VolumeSize.Suffix',
fieldLabel: 'Label',
hideLabel: true,
store: 'DefaultSizeRangeStore',
valueField: 'key',
displayField: 'value',
editable: false,
forceSelection: true,
flex: 1
},
{
xtype: 'container',
flex: 4
}
]
},
{
xtype: 'displayfield',
margin: '0 0 30 0',
value: 'Duplicati splitts his backup archives into smaller chunks. This setting defines what the maximum filesize is for this chunks.',
hideEmptyLabel: false,
hideLabel: false,
anchor: '100%'
},
{
xtype: 'textfield',
fieldLabel: 'Backup file prefix',
anchor: '100%'
},
{
xtype: 'displayfield',
value: 'This prefix is used for all backup file names. This must be set to unique values if multiple backups are stored in the same target path.',
hideEmptyLabel: false,
hideLabel: false,
anchor: '100%'
}
]
},
{
xtype: 'propertygrid',
height: 115,
margin: 10,
autoScroll: true,
title: 'Advanced',
scroll: 'vertical',
columnLines: true,
nameColumnWidth: 180,
tools: [
{
xtype: 'tool',
id: 'tAddOverride',
type: 'plus'
}
],
source: {
'Property 1': 'String',
'Property 2': true,
'Property 3': '2012-07-28T23:31:46',
'Property 4': 123
}
}
]
}
]
}
],
dockedItems: [
{
xtype: 'toolbar',
frame: false,
height: 40,
width: 40,
vertical: true,
dock: 'bottom',
layout: {
align: 'middle',
pack: 'end',
padding: 0,
type: 'hbox'
},
items: [
{
xtype: 'buttongroup',
border: '',
minButtonWidth: 100,
titleCollapse: false,
columns: 2,
layout: {
columns: 2,
type: 'table'
},
items: [
{
xtype: 'button',
frame: false,
id: 'btnClose',
scale: 'medium',
text: 'Close'
}
]
},
{
xtype: 'buttongroup',
border: '',
minButtonWidth: 100,
titleCollapse: false,
columns: 2,
layout: {
columns: 2,
type: 'table'
},
items: [
{
xtype: 'button',
id: 'btnNext',
scale: 'medium',
text: 'Next >'
}
]
}
]
}
],
listeners: {
}
});
me.callParent(arguments);
},
onSLabelChange: function(field, newValue, oldValue, options) {
//Add new Label, by capturing the typing of the user
},
onLocationsAdded: function(abstractcomponent, container, pos, options) {
// calculate consumed space of entry
},
onChkRunRegularChange: function(field, newValue, oldValue, options) {
Ext.Array.forEach(Ext.getCmp("fsSchedule").query("combobox,datefield,timefield,numberfield,checkboxgroup"), function(field) {
field.setDisabled(!newValue);
if (!Ext.isIE6 && field.el != null) {
field.el.animate({opacity: !newValue ? .5 : 1});
}
});
}
});
@@ -1,67 +0,0 @@
Ext.define('Duplicati.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 (Duplicati.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 ' + Duplicati.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() {
Duplicati.service.reconnectNow();
}
}]
});
this.dialogWindow.show();
}
}
});
@@ -1,37 +0,0 @@
Ext.define('Duplicati.view.StatuswindowFooter' ,{
extend: 'Ext.panel.Panel',
alias : 'widget.statuswindowfooter',
title : 'Status line',
header: false,
border: 0,
layout: 'column',
cls: 'footer-panel',
items: [{
xtype: 'label',
html: 'A <a href="http://www.duplicati.com/news/duplicati132available" target="_blank">new version</a> is available',
handler: function() { window.open('https://www.facebook.com/pages/Duplicati/105118456272281') },
columnWidth: 1,
margin: 10
},{
xtype: 'button',
text: 'Facebook',
handler: function() { window.open('https://www.facebook.com/pages/Duplicati/105118456272281') },
margin: 10
},{
xtype: 'button',
text: 'Google+',
handler: function() { window.open('https://plus.google.com/105271984558189185842/posts') },
margin: 10
},{
xtype: 'button',
text: 'Donate!',
handler: function() { window.open('https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=paypal%40hexad%2edk&item_name=Duplicati%20Donation&no_shipping=2&no_note=1&tax=0&currency_code=EUR&bn=PP%2dDonationsBF&charset=UTF%2d8&lc=US') },
margin: 10
}],
initComponent: function() {
this.callParent(arguments);
}
});
@@ -1,138 +0,0 @@
Ext.define('Duplicati.view.StatuswindowHeader' ,{
extend: 'Ext.panel.Panel',
alias : 'widget.statuswindowheader',
title : 'Main App controls',
header: false,
border: 0,
layout: 'column',
cls: 'header-panel',
items: [{
xtype: 'button',
cls: 'main-button',
text: 'Duplicati',
iconCls: 'unused-marker',
minHeight: 35,
id: 'status-window-header-main-button',
margin: 10,
menu: [{
id: 'status-window-header-pause-menu',
text: 'Pause Duplicati',
handler: function() { Duplicati.service.togglePause(); }
},{
id: 'status-window-header-pause-duration-menu',
xtype: 'form',
layout: 'hbox',
plain: true,
items: [{
xtype: 'label',
cls: 'x-menu-item-text',
text: 'Pause '
},{
id: 'status-window-header-pause-duration-picker',
cls: 'x-menu-item-text',
xtype: 'numberfield',
hideLabel: true,
minValue: 1,
maxValue: 600,
value: 5,
flex: 1,
handler: function() { Duplicati.service.pause('5m'); }
},{
xtype: 'label',
cls: 'x-menu-item-text',
text: ' min.'
}]
}/*{
text: 'Pause for x minutes',
menu: [{
text: 'Pause for 5 minutes',
handler: function() { Duplicati.service.pause('5m'); }
},{
text: 'Pause for 15 minutes',
handler: function() { Duplicati.service.pause('15m'); }
},{
text: 'Pause for 30 minutes',
handler: function() { Duplicati.service.pause('30m'); }
},{
text: 'Pause for 60 minutes',
handler: function() { Duplicati.service.pause('60m'); }
}]
}*/,{
text: '*** Throttle ...'
},{
xtype: 'menuseparator'
},{
text: '*** Run backups',
menu: [{
text: 'All backups'
},{
text: 'Label: Work'
},{
text: 'Label: Home'
},{
text: 'Label: Amazon S3'
}]
},{
xtype: 'menuseparator'
},{
text: '*** Settings'
},{
text: 'About',
handler: function() { Duplicati.view.AboutWindow.show(); }
}]
},{
xtype: 'label',
html: '&nbsp;',
columnWidth: 1
},{
xtype: 'panel',
layout: 'vbox',
align: 'center',
margin: 5,
border: 0,
items: [{
xtype: 'label',
cls: 'throttle-label',
text: '*** Throttle upload'
},{
xtype: 'slider',
width: 200,
value: 80,
minValue: 0,
maxValue: 100
}]
},{
xtype: 'button',
cls: 'add-new-backup-button',
text: 'Add new backup',
iconCls: 'unused-marker',
minHeight: 35,
margin: 10,
handler: function() {
Ext.create('Ext.window.Window', {
title: 'Add new backup',
bodyBorder: false,
layout: 'fit',
items: {
xtype: 'backupconfigpanel'
}
}).show();
}
},{
xtype: 'button',
id: 'status-window-header-pause-button',
cls: 'pause-backup-button',
iconCls: 'backups-paused',
minHeight: 35,
text: 'Pause',
margin: 10,
handler: function() { Duplicati.service.togglePause(); }
}],
initComponent: function() {
this.callParent(arguments);
}
});
@@ -1,229 +0,0 @@
Ext.define('Duplicati.view.override.BackupConfig', {
requires: 'Duplicati.view.BackupConfig'
}, function() {
Ext.override(Duplicati.view.BackupConfig, {
setFieldValue: function(fieldId, val) {
var field = this.getForm().findField(fieldId);
if (field) {
field.setValue(val);
if (this.trackResetOnLoad) {
field.resetOriginalValue();
}
return true;
} else {
Ext.log('No mapping for field ' + fieldId);
return false;
}
},
setValues: function(record, parentFieldName) {
var me = this;
var form = me.getForm();
function setVal(fieldId, val) {
if (parentFieldName) {
fieldId = parentFieldName + '.' + fieldId;
}
var field = form.findField(fieldId);
if (field) {
field.setValue(val);
if (me.trackResetOnLoad) {
field.resetOriginalValue();
}
} else if(Ext.isObject(val)) {
me.setValues(val, fieldId);
} else {
Ext.log('No mapping for field ' + fieldId);
}
}
if (record.getData) {
Ext.iterate(record.getData(), setVal);
if (record.getAssociatedData && record.getAssociatedData()) {
for(k in record.getAssociatedData()) {
//The property name has a lower first character, but the method format is getCamelCase()
var propName = k[0].toUpperCase() + k.substring(1);
if (record['get' + propName] != null)
me.setValues(record['get' + propName](), parentFieldName + '.' + propName);
}
}
}
return this;
},
updateRecord: function(record) {
var values = this.getFieldValues(),
name,
obj = {};
alert( "Servus updateRecord" );
function populateObj(record, values) {
var obj = {},
name;
record.fields.each(function(field) {
name = field.name;
if (field.model) {
var nestedValues = {};
var hasValues = false;
for(var v in values) {
if (v.indexOf('.') > 0) {
var parent = v.substr(0, v.indexOf('.'));
if (parent == field.name) {
var key = v.substr(v.indexOf('.') + 1);
nestedValues[key] = values[v];
hasValues = true;
}
}
}
if (hasValues) {
obj[name] = populateObj(Ext.create(field.model), nestedValues);
}
} else if (name in values) {
obj[name] = values[name];
}
});
return obj;
}
obj = populateObj(record, values);
record.beginEdit();
record.set(obj);
record.endEdit();
return this;
},
setEncryptionModule: function(value) {
value = value || '';
var form = this.getForm();
var combo = form.findField('Task.EncryptionModule');
var store = combo.getStore();
//Make sure we have the empty element
if (store.findRecord("id", -1) == null) {
store.add({encryptionMethodName: 'No encryption', encryptionMethodIdentifier: '', id: -1});
}
this.setFieldValue('Task.EncryptionModule', value);
},
setEncryptionPassword: function(value) {
value = value || '';
this.setFieldValue('sEncryptionPassword', value);
this.setFieldValue('sEncryptionPasswordCheck', value);
},
setBackupRepeatAndWhen: function(valueRepeat, valueWhen) {
valueWhen = valueWhen || '';
valueRepeat = valueRepeat || '';
var form = this.getForm();
var chk = form.findField('chkRunRegular');
if (valueWhen == '' || valueRepeat == '') {
chk.setValue(false);
} else {
chk.setValue(true);
var date = Duplicati.Utility.parseJsonDate(valueWhen);
this.setFieldValue('Schedule.Repeat.Number', parseInt(valueRepeat.substr(0, valueRepeat.length - 1)));
this.setFieldValue('Schedule.Repeat.Suffix', valueRepeat.substr(valueRepeat.length - 1, 1));
this.setFieldValue('Schedule.When.Time', date);
this.setFieldValue('Schedule.When.Date', date);
}
},
setAllowedWeekdays: function(value) {
var form = this.getForm();
var t = form.findField('Schedule.AllowedWeekdays');
},
setVolumeSize: function(value) {
value = value || '';
var number = parseInt(value);
var suffix = 'b';
function isNumber(n) {
switch(n) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}
if (value != '' && value.length >= 2) {
var i = value.length - 1;
while(i >= 0 && !isNumber(value[i]))
i--;
i++;
suffix = value.substr(i, value.length - i).toLowerCase();
number = parseInt(value.substr(0, i));
}
this.setFieldValue('Task.Extensions.VolumeSize.Number', number);
this.setFieldValue('Task.Extensions.VolumeSize.Suffix', suffix);
},
setSourcePaths: function(value) {
var store = Ext.getCmp('Locations').getStore();
store.removeAll();
if (value != null && value != '') {
var pathSep = Duplicati.service.serverdata['system-info'].PathSeparator;
Ext.Array.each(value.split(pathSep), function(rec){
Ext.getCmp('Locations').getStore().add(
new Duplicati.model.TaskItems.BackupLocation ( {
Location: rec,
TotalSize:0
})
);
});
}
},
loadRecord: function(loaderObject) {
var schedule = loaderObject.getSchedule();
var task = loaderObject.getTask();
this.setValues(schedule, "Schedule")
this.setValues(task, "Task")
this.setEncryptionModule(task.getData().EncryptionModule);
this.setEncryptionPassword(task.getData().Encryptionkey);
this.setBackupRepeatAndWhen(schedule.getData().Repeat, schedule.getData().When);
this.setAllowedWeekdays(schedule.getData().AllowedWeekdays);
this.setVolumeSize(task.getExtensions().getData().VolumeSize);
this.setSourcePaths(task.getData().SourcePath);
}
});
});
@@ -1,107 +0,0 @@
Ext.define('Duplicati.view.schedule.List' ,{
extend: 'Ext.grid.Panel',
alias : 'widget.schedulelist',
title : 'All Schedules',
header: false,
border: 0,
id: 'status-window-schedule-list',
hideHeaders: true,
selType: 'rowmodel',
store: 'Schedules',
elementTemplateStr:
'<span class="backup-schedule-name" title="Click for actions - {Name}" onclick="Duplicati.ListUtility.showContextMenu({ID}, this);"><span class="backup-schedule-name-inner">{Name}<div class="backup-schedule-drop-arrow"></div></span></span>' +
'<span class="backup-schedule-details">' +
'<span class="backup-schedule-details-inner">' +
/* The template for this became un-readable, so now it is a function */
'{[Duplicati.ListUtility.formatBackupScheduleDetails(values)]}' +
'</span>' +
'<tpl if="Path != null && Path != \'\'">' +
'<div class="backup-schedule-tags">' +
'<div class="schedule-tags-icon"></div><span>Labels: <span>{Path}</span></span>' +
'</div>' +
'</tpl>' +
'</span>',
elementTemplate: null,
elementContextMenu: Ext.create('Ext.menu.Menu', {
floating: true,
items: [{
text: '*** Show files'
},{
text: 'Run now',
handler: function() {
Ext.log('Running backup ' + Duplicati.ListUtility.currentScheduleId);
Duplicati.service.runBackup(Duplicati.ListUtility.currentScheduleId, false);
}
},{
text: 'Run a full backup now',
handler: function() {
Ext.log('Running full backup ' + Duplicati.ListUtility.currentScheduleId);
Duplicati.service.runBackup(Duplicati.ListUtility.currentScheduleId, true);
}
},{
text: '*** Cancel'
},{
xtype: 'menuseparator'
},{
text: 'Edit settings',
handler: function() {
Ext.create('Ext.window.Window', {
layout: 'fit',
bodyBorder: false,
title: 'Edit backup',
items: [
Ext.create('Duplicati.view.BackupConfig', {
scheduleId: Duplicati.ListUtility.currentScheduleId
})
]
}).show();
}
},{
text: '*** Delete backup'
},{
xtype: 'menuseparator'
},{
text: '*** Create a copy'
}]
}),
columns:
[
{header: 'ScheduleTime', dataIndex: 'NextScheduledTime', flex: 0.8, align: 'center', renderer:
function(value, metaData, record) {
var schedulePos = Duplicati.service.getSchedulePosition(record.get("ID"));
if (schedulePos == 0) {
return '<div class="schedule-activity-text schedule-running-info"><div>In progress</div><div><a href="#" onclick="Duplicati.service.cancelJob('+ record.get("ID") +')">Cancel</a></div></div><div class="info-icon schedule-active"></div>';
} else if (schedulePos > 0) {
return '<div class="schedule-activity-text schedule-queue-info">No. ' + schedulePos + ' in queue</div><div class="info-icon schedule-in-queue"></div>';
} else if (value != null) {
var scdate = Duplicati.Utility.parseJsonDate(value);
if (scdate > new Date().getTime())
return '<div class="schedule-activity-text schedule-time-info" title="' + scdate.toLocaleString() + '"><span class="marker-time-ago" title="' + scdate.toUTCString() + '"></span>' + Duplicati.Utility.timeAgo(scdate) + '</div><div class="info-icon schedule-waiting"></div>';
}
return '';
}
},
{header: 'Name', dataIndex: 'Name', flex: 1, align: 'center', renderer:
function(value, metaData, record) {
return this.elementTemplate.apply(record.data);
}
},
{header: 'Path', dataIndex: 'ID', flex: 0.8, align: 'left', renderer:
function(value) { return value; }
}
],
initComponent: function() {
this.elementTemplate = new Ext.XTemplate(this.elementTemplateStr, {formatSizeString: function(v) { return Duplicati.Utility.formatSizeString(v); } });
this.callParent(arguments);
}
});
@@ -1,14 +0,0 @@
Ext.define('Duplicati.view.wndAddFilter', {
extend: 'Ext.window.Window',
height: 342,
width: 550,
title: 'Add Filter',
initComponent: function() {
var me = this;
me.callParent(arguments);
}
});
@@ -1,70 +0,0 @@
Ext.define('Duplicati.view.wndAddLocation', {
extend: 'Ext.window.Window',
height: 539,
id: 'winAddLocation',
width: 349,
title: 'Add Location',
modal: true,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [
{
xtype: 'treepanel',
height: 467,
id: 'treeLocation',
iconCls: '',
title: 'My Computer',
hideHeaders: true,
store: 'MyComputerTreeStore',
folderSort: true,
rootVisible: false,
singleExpand: true,
useArrows: true,
viewConfig: {
autoScroll: true,
blockRefresh: true,
loadingText: 'Retrieving File Structure',
multiSelect: true,
simpleSelect: true
}
}
],
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
layout: {
pack: 'end',
type: 'hbox'
},
items: [
{
xtype: 'buttongroup',
columns: 2,
layout: {
columns: 2,
type: 'table'
},
items: [
{
xtype: 'button',
id: 'btnAddLocations',
maintainFlex: false,
scale: 'medium',
text: 'Add selected Nodes'
}
]
}
]
}
]
});
me.callParent(arguments);
}
});
@@ -1,16 +0,0 @@
Ext.define('Duplicati.view.wndCreateConnection', {
extend: 'Ext.window.Window',
height: 342,
id: 'wndCreateConnection',
width: 418,
title: 'Create Connection',
titleCollapse: false,
initComponent: function() {
var me = this;
me.callParent(arguments);
}
});
-162
View File
@@ -1,162 +0,0 @@
function parseBool(v) {
if (v == null)
return false;
if (typeof(v) == 'boolean')
return v;
v = (v + '').toLowerCase();
return (v == 'true' || v == 'on' || v == '1');
}
{
// This helps in a debug setup
var extdefined = false;
try { extdefined = Ext !== undefined; } catch (e) {}
if (!extdefined) { alert('ExtJS failed to load!\n If this is a debug build,\nplease download and extract:\n\nExtJS 4.2.0\n\ninto the folder:\nDuplicati/Server/webroot/extjs-4.2.0'); }
delete extdefined;
}
Ext.application({
requires: [
'Ext.container.Viewport',
'Ext.layout.container.Border',
'Duplicati.Service',
'Duplicati.Utility',
'Duplicati.ListUtility',
'Duplicati.view.AboutWindow',
'Duplicati.view.LostConnectionWindow',
// Override for handling nested Model 2 Form
'Duplicati.view.override.BackupConfig',
'Duplicati.model.override.BackupJob'
],
name: 'Duplicati',
appFolder: 'Duplicati',
controllers: [
'Schedules',
'StatuswindowHeader',
'StatuswindowFooter',
'BackupConfig'
],
stores: [
'LabelStore',
'EncryptionMethodStore',
'AdditionalPathStore',
'MyComputerTreeStore',
'BackupJob',
'DefaultTimeRangesStore',
'NewBackupChainWhenStore',
'DeleteOldChainsWhenStore',
'DefaultSizeRangeStore'
],
views: [
'BackupConfig',
'wndAddLocation',
'wndAddFilter',
'wndCreateConnection'
],
models: [
'BackupJob',
'Schedule',
'Task',
'TaskItems.BackupLocation',
'TaskItems.CompressionSettings',
'TaskItems.EncryptionSettings',
'TaskItems.Overrides',
'TaskItems.Extensions',
'TaskItems.BackendSettings',
'ScheduleItems.Metadata'
],
//This object encapsulates all access to the web service
service: null,
launch: function() {
Ext.log = function(msg) {
console.log(msg);
}
//Pretend the app fires events too
this.addEvents('current-state-updated', 'count-down-pause-timer');
//Make a service object
this.service = new Duplicati.Service();
//Make the service globally accesible
Duplicati.service = this.service;
Duplicati.instance = this;
Duplicati.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');
}
}
}
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() {
Duplicati.view.LostConnectionWindow.show();
},
'reconnected': function() {
Duplicati.view.LostConnectionWindow.hide();
},
'lost-connection-retry': function() {
Duplicati.view.LostConnectionWindow.setStatusAsRunning();
},
'lost-connection-retry-delay': function(seconds) {
Duplicati.view.LostConnectionWindow.setStatusAsWaiting(seconds);
},
'count-down-pause-timer': function(e) {
Duplicati.instance.fireEvent('count-down-pause-timer', e);
},
scope: this
});
//Fetch the current status
this.service.updateCurrentState();
Ext.create('Ext.container.Viewport', {
layout: 'border',
items: [{
region: 'center',
xtype: 'schedulelist'
},{
region: 'north',
xtype: 'statuswindowheader'
},{
region: 'south',
xtype: 'statuswindowfooter'
}],
renderTo: Ext.getBody()
});
}
});
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 988 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

@@ -1,22 +0,0 @@
<!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="X-UA-Compatible" content="IE=9" />
<title>Duplicati Backup</title>
<link rel="stylesheet" type="text/css" href="http://cdn.sencha.io/ext-4.2.0-gpl/resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/common.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/status-window.css" />
<link rel="stylesheet" type="text/css" href="stylesheets/customized.css" />
<script type="text/javascript" src="http://cdn.sencha.io/ext-4.2.0-gpl/ext-all.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="scripts/customized.js"></script>
</head>
<body>
</body>
</html>
@@ -1,217 +0,0 @@
.footer-panel .x-panel-body
{
background-color: #ccffcc;
}
.header-panel .x-panel-body
{
background-color: #ccffcc;
}
.main-button .x-btn-arrow, .add-new-backup-button .x-btn-center, .pause-backup-button .x-btn-center
{
height: 40px;
}
.main-button .x-btn-inner, .add-new-backup-button .x-btn-inner, .pause-backup-button .x-btn-inner
{
font-size: 2em;
height: 20px;
padding-left: 36px;
}
.main-button .x-btn-icon, .add-new-backup-button .x-btn-icon, .pause-backup-button .x-btn-icon
{
width: 32px;
height: 32px;
top: 4px;
}
.main-button .x-btn-icon
{
background-image: url(../icons/main-logo.png);
}
.add-new-backup-button .x-btn-icon
{
background-image: url(../icons/add-backup.png);
}
.pause-backup-button .backups-paused
{
background-image: url(../icons/status-play.png);
}
.pause-backup-button .backups-running
{
background-image: url(../icons/status-pause.png);
}
.throttle-label
{
font-size: 2em;
padding-left: 20px;
}
.low-storage-space
{
color: red;
}
.important-information
{
font-weight: bold;
}
.info-icon
{
padding: 8px;
margin-right: 4px;
margin-top: 40px;
background-repeat: no-repeat;
background-position-y: 4px;
display: inline;
float: right;
}
.schedule-activity-text
{
margin-top: 40px;
margin-right: 20px;
display: inline;
float: right;
}
.schedule-waiting
{
background: url(../icons/schedule-waiting.png)
}
.schedule-active
{
background: url(../icons/schedule-active.png)
}
.schedule-in-queue
{
background: url(../icons/schedule-in-queue.png)
}
.backup-schedule-tags
{
padding-top: 2px;
}
.marker-time-ago
{
display: none;
}
.backup-schedule-detail-source-size,
.backup-schedule-detail-backup-size,
.backup-schedule-detail-free-size,
.backup-schedule-detail-change-count,
.backup-schedule-detail-last-backup,
.backup-schedule-tags
{
display: block;
padding-left: 15px;
padding-right: 15px;
text-align: left;
}
.backup-schedule-details-inner
{
padding-left: 15px;
padding-right: 15px;
text-align: left;
}
.backup-schedule-name
{
display: block;
border: 1px lightgrey solid;
margin-left: 20px;
margin-right: 20px;
padding-top: 8px;
padding-bottom: 8px;
margin-top: 10px;
background-color: #aaeeaa;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
-khtml-border-radius: 6px;
border-radius: 6px;
}
.backup-schedule-drop-arrow
{
background-image: url(../extjs-4.1.0/resources/themes/images/default/button/arrow.gif);
background-repeat: no-repeat;
width: 16px;
height: 10px;
background-position-x: 6px;
display: inline-block;
}
.backup-schedule-name-inner
{
display: block;
font-weight: bold;
font-size: 1.5em;
overflow: hidden;
white-space: wrap;
margin-left: 8px;
margin-right: 8px;
padding-top: 2px;
padding-bottom: 4px;
cursor: pointer;
}
.backup-schedule-details
{
display: block;
border: 1px lightgrey solid;
padding-top: 10px;
padding-bottom: 8px;
padding-left: 4px;
padding-right: 4px;
overflow: auto;
white-space: normal;
margin-bottom: 10px;
background-color: #ccffcc;
margin-top: -2px;
font-size: 1.2em;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
-khtml-border-radius: 6px;
border-radius: 6px;
}
#status-window-header-pause-duration-menu
{
color: #222;
font-size: 11px;
}
#status-window-header-pause-duration-menu div
{
padding-left: 32px;
border: 0px none;
background-color: transparent;
}
#status-window-header-pause-duration-picker
{
margin-left: 6px;
margin-right: 6px;
}
#status-window-header-pause-duration-picker div
{
padding-left: 0px;
}
-71
View File
@@ -1,71 +0,0 @@
<html>
<body>
<form action="control.cgi" method="post">
<input type="text" name="action" value="add-schedule" />
<br/>
<textarea name="schedule" cols=50 rows=12>{
"NextScheduledTime": "\/Date(1343991600000+0200)\/",
"AllowedWeekdays": null,
"ID": 1,
"Name": "Created from FORM",
"Path": "",
"When": "\/Date(1338289200000+0200)\/",
"Repeat": "1D",
"Weekdays": ""
}</textarea>
<br/>
<textarea name="task" cols=50 rows=20>{
"ID": 1,
"Service": "file",
"Encryptionkey": "",
"SourcePath": "C:\\boot\\",
"ScheduleID": 1,
"KeepFull": 4,
"KeepTime": "",
"FullAfter": "1M",
"IncludeSetup": false,
"EncryptionModule": "aes",
"CompressionModule": "",
"BackendSettings": {
"UI: Checked empty": "true",
"Destination": "C:\\testbackup_forms\\backup1_create_by_form",
"Username": "",
"Password": ""
},
"Extensions": {
"Upload Bandwidth": "",
"Download Bandwidth": "",
"Max Upload Size": "",
"Volume Size": "25MB",
"Thread Priority": "",
"Async Transfer": "True",
"Ignore Timestamps": "False",
"File Size Limit": "",
"Disable AES fallback encryption": "True",
"Select Files - Version": "2",
"Select Files - Use Simple Mode": "False",
"Select Files - Include Documents": "True",
"Select Files - Include Desktop": "True",
"Select Files - Include Music": "False",
"Select Files - Include Images": "True",
"Select Files - Include AppData": "False",
"Select When - Warned No Schedule": "False",
"Select When - Warned Too Many Incrementals": "False",
"Select When - Warned No Incrementals": "False",
"Password Settings - Warned No Password": "True",
"Cleanup Settings - Warned No Cleanup": "False"
},
"Overrides": {},
"EncryptionSettings": {},
"CompressionSettings": {},
"Filter": ""
}</textarea>
<br/>
<input type="submit" value="Submit!" />
</form>
</body>
</html>
-72
View File
@@ -1,72 +0,0 @@
<html>
<body>
<form action="control.cgi" method="post">
<input type="text" name="action" value="update-schedule" />
<input type="text" name="id" value="3" />
<br/>
<textarea name="schedule" cols=50 rows=12>{
"NextScheduledTime": "\/Date(1343991600000+0200)\/",
"AllowedWeekdays": null,
"ID": 1,
"Name": "Updated from FORM",
"Path": "",
"When": "\/Date(1338289200000+0200)\/",
"Repeat": "1D",
"Weekdays": ""
}</textarea>
<br/>
<textarea name="task" cols=50 rows=20>{
"ID": 1,
"Service": "file",
"Encryptionkey": "",
"SourcePath": "C:\\boot\\",
"ScheduleID": 1,
"KeepFull": 4,
"KeepTime": "",
"FullAfter": "1M",
"IncludeSetup": false,
"EncryptionModule": "aes",
"CompressionModule": "",
"BackendSettings": {
"UI: Checked empty": "true",
"Destination": "C:\\testbackup_forms\\backup1_update_by_form",
"Username": "",
"Password": ""
},
"Extensions": {
"Upload Bandwidth": "",
"Download Bandwidth": "",
"Max Upload Size": "",
"Volume Size": "50MB",
"Thread Priority": "",
"Async Transfer": "True",
"Ignore Timestamps": "False",
"File Size Limit": "",
"Disable AES fallback encryption": "True",
"Select Files - Version": "2",
"Select Files - Use Simple Mode": "False",
"Select Files - Include Documents": "True",
"Select Files - Include Desktop": "True",
"Select Files - Include Music": "False",
"Select Files - Include Images": "True",
"Select Files - Include AppData": "False",
"Select When - Warned No Schedule": "False",
"Select When - Warned Too Many Incrementals": "False",
"Select When - Warned No Incrementals": "False",
"Password Settings - Warned No Password": "True",
"Cleanup Settings - Warned No Cleanup": "False"
},
"Overrides": {},
"EncryptionSettings": {},
"CompressionSettings": {},
"Filter": ""
}</textarea>
<br/>
<input type="submit" value="Submit!" />
</form>
</body>
</html>