1594 lines
54 KiB
JavaScript
1594 lines
54 KiB
JavaScript
/*
|
|
* Primary app code
|
|
*/
|
|
|
|
// Global app settings
|
|
|
|
APP_DATA = null;
|
|
APP_EVENTS= {};
|
|
APP_UTIL = {
|
|
parseBoolOption: function(val, def) {
|
|
if (val == null) {
|
|
if (def === undefined)
|
|
return true;
|
|
else
|
|
return def == true;
|
|
}
|
|
|
|
var str = (val + '').toLowerCase();
|
|
return str == '' || str == 'true' || str == '1' || str == 'yes' || str == 'on';
|
|
},
|
|
|
|
isValidBoolOption: function(val) {
|
|
if (val == null)
|
|
return true;
|
|
|
|
var t = (val + '').toLowerCase();
|
|
return val == '' || t == '1' || t == 'true' || t == 'on' || t == 'yes' || t == '0' || t == 'false' || t == 'off' || t == 'no';
|
|
},
|
|
|
|
parseOptionStrings: function(val, dict, validateCallback) {
|
|
dict = dict || {};
|
|
var lines = replace_all(val || '', '\r', '\n').split('\n');
|
|
for(var i in lines) {
|
|
var line = lines[i].trim();
|
|
if (line != '' && line[0] != '#') {
|
|
if (line.indexOf('--') == 0) {
|
|
line = line.substr(2);
|
|
}
|
|
|
|
var eqpos = line.indexOf('=');
|
|
var key = line;
|
|
var value = true;
|
|
if (eqpos > 0) {
|
|
key = line.substr(0, eqpos).trim();
|
|
value = line.substr(eqpos + 1).trim();
|
|
if (value == '')
|
|
value = true;
|
|
}
|
|
|
|
if (validateCallback)
|
|
if (!validateCallback(dict, key, value))
|
|
return null;
|
|
|
|
dict['--' + key] = value;
|
|
}
|
|
}
|
|
|
|
return dict;
|
|
},
|
|
|
|
fill_form: function(form, data, map, extra) {
|
|
map = map || {};
|
|
data = data || {};
|
|
|
|
for(var k in data) {
|
|
var key = k;
|
|
var m = map[key];
|
|
var v = data[k];
|
|
|
|
if (m !== false) {
|
|
if (m && typeof(m) == typeof(''))
|
|
key = m;
|
|
|
|
if (m && typeof(m) == typeof(function() {})) {
|
|
m(data, key, v, extra);
|
|
} else {
|
|
var n = form.find('#' + key);
|
|
if (n.attr('type') == 'checkbox') {
|
|
n.attr('checked', APP_UTIL.parseBoolOption(v));
|
|
} else {
|
|
n.val(v);
|
|
}
|
|
|
|
n.change();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
read_form: function(form, map, values, extra) {
|
|
values = values || {};
|
|
map = map || {};
|
|
|
|
form.find('select').each(function(i, e) {
|
|
var key = e.id;
|
|
var m = map[e.id];
|
|
|
|
if (m !== false) {
|
|
if (m && typeof(m) == typeof(function() {})) {
|
|
m(values, key, e, extra);
|
|
} else {
|
|
if (m && typeof(m) == typeof(''))
|
|
key = m;
|
|
|
|
values[key] = $(e).val();
|
|
}
|
|
}
|
|
});
|
|
|
|
form.find('textarea').each(function(i, e) {
|
|
var key = e.id;
|
|
var m = map[e.id];
|
|
|
|
if (m !== false) {
|
|
if (m && typeof(m) == typeof(function() {})) {
|
|
m(values, key, e, extra);
|
|
} else {
|
|
if (m && typeof(m) == typeof(''))
|
|
key = m;
|
|
|
|
values[key] = $(e).val();
|
|
}
|
|
}
|
|
});
|
|
|
|
form.find('input').each(function(i, e) {
|
|
var key = e.id;
|
|
var m = map[e.id];
|
|
|
|
if (m !== false) {
|
|
if (m && typeof(m) == typeof(function() {})) {
|
|
m(values, key, e, extra);
|
|
} else {
|
|
if (m && typeof(m) == typeof(''))
|
|
key = m;
|
|
|
|
if (e.type == 'checkbox')
|
|
values[key] = $(e).is(':checked');
|
|
else
|
|
values[key] = $(e).val();
|
|
}
|
|
}
|
|
});
|
|
|
|
return values;
|
|
}
|
|
};
|
|
|
|
$(document).ready(function() {
|
|
|
|
// Flag as loaded in case we have plugins
|
|
APP_DATA = {
|
|
plugins: {
|
|
backend: {},
|
|
compression: {},
|
|
encryption: {},
|
|
primary: {}
|
|
|
|
}
|
|
};
|
|
|
|
var PRIVATE_DATA = {};
|
|
|
|
$('#main-appname').text(APP_CONFIG.branded_name);
|
|
|
|
window.document.title = APP_CONFIG.branded_name;
|
|
|
|
if ((APP_CONFIG.branded_subtitle || '').length > 0) {
|
|
var subdiv = $('<div id="main-appname-subtitle">');
|
|
subdiv.text(APP_CONFIG.branded_subtitle);
|
|
$('#main-appname').append(subdiv);
|
|
$('#main-appname').addClass('has-subtitle');
|
|
}
|
|
|
|
$('.button').button();
|
|
|
|
$('#main-list-container > div.main-backup-entry').remove();
|
|
$('#loading-dialog').dialog({modal: true}).show();
|
|
|
|
jQuery.timeago.settings.allowFuture = true;
|
|
jQuery.timeago.settings.allowPast = true;
|
|
|
|
$.noty.defaults.layout = 'bottomCenter';
|
|
|
|
// Register a global function for password strength
|
|
$.passwordStrength = function(password, callback) {
|
|
if (callback == null)
|
|
return;
|
|
|
|
var onUpdate = function(res) {
|
|
try { callback(res); }
|
|
catch (e) { }
|
|
};
|
|
|
|
try { onUpdate(zxcvbn(password)); }
|
|
catch (e) {
|
|
// Not loaded, try this:
|
|
$.getScript('/scripts/zxcvbn.js', function() {
|
|
try {
|
|
onUpdate(zxcvbn(password));
|
|
}
|
|
catch (e) {
|
|
onUpdate(null);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
var formatSizes = ['TB', 'GB', 'MB', 'KB'];
|
|
$.formatSizeString = function(val) {
|
|
val = parseInt(val || 0);
|
|
var max = formatSizes.length;
|
|
for(var i = 0; i < formatSizes.length; i++) {
|
|
var m = Math.pow(1024, max - i);
|
|
if (val > m)
|
|
return (val / m).toFixed(2) + ' ' + formatSizes[i];
|
|
}
|
|
|
|
return val + ' ' + bytes;
|
|
};
|
|
|
|
pwz = function(i, c) {
|
|
i += '';
|
|
while(i.length < c)
|
|
i = '0' + i;
|
|
return i;
|
|
}
|
|
|
|
$.toDisplayDateAndTime = function(dt) {
|
|
return pwz(dt.getFullYear(), 4) + '-' + pwz(dt.getMonth() + 1, 2) + '-' + pwz(dt.getDate(), 2) + ' ' + pwz(dt.getHours(), 2) + ':' + pwz(dt.getMinutes(), 2);
|
|
};
|
|
|
|
$.parseDate = function(dt) {
|
|
if (typeof(dt) == typeof('')) {
|
|
var msec = Date.parse(dt);
|
|
if (isNaN(msec)) {
|
|
if (dt.length == 16 && dt[8] == 'T' && dt[15] == 'Z') {
|
|
dt = dt.substr(0, 4) + '-' + dt.substr(4, 2) + '-' + dt.substr(6, 2) + 'T' +
|
|
dt.substr(9, 2) + ':' + dt.substr(11, 2) + ':' + dt.substr(13, 2) + 'Z';
|
|
}
|
|
return new Date(dt);
|
|
} else {
|
|
return new Date(msec);
|
|
}
|
|
}
|
|
else
|
|
return new Date(dt);
|
|
};
|
|
|
|
var serverWithCallback = function(data, callback, errorhandler, refreshMethod) {
|
|
if (typeof(data) == typeof(''))
|
|
data = { action: data };
|
|
|
|
var method = 'GET';
|
|
if (data.HTTP_METHOD) {
|
|
method = data.HTTP_METHOD;
|
|
delete data.HTTP_METHOD;
|
|
}
|
|
|
|
$.ajax({
|
|
url: APP_CONFIG.server_url,
|
|
type: method,
|
|
dataType: 'json',
|
|
data: data
|
|
})
|
|
.done(function(data) {
|
|
if (refreshMethod)
|
|
refreshMethod(data, true, null);
|
|
|
|
if (callback != null)
|
|
callback(data, true, null);
|
|
})
|
|
.fail(function(data, status) {
|
|
var msg = data.statusText;
|
|
if (data && data.responseJSON && data.responseJSON.Message)
|
|
msg = data.responseJSON.Message;
|
|
|
|
if (refreshMethod)
|
|
refreshMethod(data, false, msg);
|
|
|
|
if (errorhandler)
|
|
errorhandler(data, false, msg);
|
|
});
|
|
};
|
|
|
|
PRIVATE_DATA.server_state = {
|
|
polling: false,
|
|
eventId: -1,
|
|
state: null,
|
|
failed: false,
|
|
dataEventId: -1,
|
|
|
|
retryTimer: null,
|
|
pauseUpdateTimer: null,
|
|
activeTask: null,
|
|
scheduled: []
|
|
};
|
|
|
|
PRIVATE_DATA.progress_state_text = {
|
|
'Backup_Begin': 'Starting ...',
|
|
'Backup_PreBackupVerify': 'Verifying backend data ...',
|
|
'Backup_PostBackupTest': 'Verifying remote data ...',
|
|
'Backup_PreviousBackupFinalize': 'Completing previous backup ...',
|
|
'Backup_ProcessingFiles': null,
|
|
'Backup_Finalize': 'Completing backup ...',
|
|
'Backup_WaitForUpload': 'Waiting for upload ...',
|
|
'Backup_Delete': 'Deleting unwanted files ...',
|
|
'Backup_Compact': 'Compacting remote data ...',
|
|
'Backup_VerificationUpload': 'Uploadind verification file ...',
|
|
'Backup_PostBackupVerify': 'Verifying backend data ...',
|
|
'Backup_Complete': 'Finished!',
|
|
'Restore_Begin': 'Starting ...',
|
|
'Restore_RecreateDatabase': 'Rebuilding local database ...',
|
|
'Restore_PreRestoreVerify': 'Verifying remote data ...',
|
|
'Restore_CreateFileList': 'Building list of files to restore ...',
|
|
'Restore_CreateTargetFolders': 'Creating target folders ...',
|
|
'Restore_ScanForExistingFiles': 'Scanning existing files ...',
|
|
'Restore_ScanForLocalBlocks': 'Scanning for local blocks ...',
|
|
'Restore_PatchWithLocalBlocks': 'Patching files with local blocks ...',
|
|
'Restore_DownloadingRemoteFiles': 'Downloading files ...',
|
|
'Restore_PostRestoreVerify': 'Verifying restored files ...',
|
|
'Restore_Complete': 'Finished!',
|
|
'Error': 'Error!'
|
|
};
|
|
|
|
PRIVATE_DATA.update_progress_and_schedules = function() {
|
|
var scheduledMap = {};
|
|
var backupMap = {};
|
|
var state = PRIVATE_DATA.server_state;
|
|
var current = state.activeTask == null ? false : 'backup-' + state.activeTask.Item2;
|
|
|
|
if (state.activeTask == null) {
|
|
$('#main-status-area-cancel-button').hide();
|
|
$('#main-status-area-progress-outer').hide();
|
|
|
|
//TODO: state.scheduled is just the current queue, we need to find the next based on "Time"
|
|
|
|
|
|
if (PRIVATE_DATA.backup_list == null || PRIVATE_DATA.backup_list.length == 0) {
|
|
$('#main-status-area-text').text('No scheduled backups waiting');
|
|
} else {
|
|
var bk = null;
|
|
var mindate = null;
|
|
for(var n in PRIVATE_DATA.backup_list) {
|
|
if (PRIVATE_DATA.backup_list[n].Schedule == null || PRIVATE_DATA.backup_list[n].Schedule.Time == null)
|
|
continue;
|
|
|
|
var selfdate = new Date(PRIVATE_DATA.backup_list[n].Schedule.Time);
|
|
if (mindate == null || selfdate < mindate) {
|
|
bk = PRIVATE_DATA.backup_list[n].Backup;
|
|
mindate = selfdate;
|
|
}
|
|
}
|
|
|
|
if (bk == null) {
|
|
$('#main-status-area-text').text('No scheduled backups waiting');
|
|
} else {
|
|
$('#main-status-area-text').text('Waiting to start "' + bk.Name + '" at ' + $.toDisplayDateAndTime(mindate));
|
|
}
|
|
}
|
|
} else {
|
|
$('#main-status-area-cancel-button').show();
|
|
$('#main-status-area-progress-outer').show();
|
|
|
|
var id = state.activeTask.Item2;
|
|
var bk = null;
|
|
|
|
for(var n in PRIVATE_DATA.backup_list)
|
|
if (PRIVATE_DATA.backup_list[n].Backup.ID == id) {
|
|
bk = PRIVATE_DATA.backup_list[n].Backup;
|
|
break;
|
|
}
|
|
|
|
if (bk == null)
|
|
$('#main-status-area-text').text('Unknown backup');
|
|
else
|
|
$('#main-status-area-text').text(bk.Name);
|
|
|
|
var txt = 'Running ...';
|
|
var pg = -1;
|
|
if (PRIVATE_DATA.server_progress.lastEvent != null) {
|
|
|
|
if (PRIVATE_DATA.server_progress.lastEvent.Phase == 'Backup_ProcessingFiles') {
|
|
|
|
if (PRIVATE_DATA.server_progress.lastEvent.StillCounting) {
|
|
txt = 'Counting (' + PRIVATE_DATA.server_progress.lastEvent.TotalFileCount + ' files found, ' + $.formatSizeString(PRIVATE_DATA.server_progress.lastEvent.TotalFileSize) + ')';
|
|
pg = 0;
|
|
} else {
|
|
var filesleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileCount - PRIVATE_DATA.server_progress.lastEvent. ProcessedFileCount;
|
|
var sizeleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileSize - PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize;
|
|
pg = PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize / PRIVATE_DATA.server_progress.lastEvent.TotalFileSize;
|
|
|
|
if (PRIVATE_DATA.server_progress.lastEvent.ProcessedFileCount == 0)
|
|
pg = 0;
|
|
else if (pg == 1)
|
|
pg = 0.95;
|
|
|
|
txt = filesleft + ' files (' + $.formatSizeString(sizeleft) + ') to go';
|
|
}
|
|
} else {
|
|
txt = PRIVATE_DATA.progress_state_text[PRIVATE_DATA.server_progress.lastEvent.Phase] || txt;
|
|
if (PRIVATE_DATA.server_progress.lastEvent.Phase == 'Backup_WaitForUpload')
|
|
pg = 1;
|
|
|
|
}
|
|
|
|
if (pg == -1) {
|
|
$('#main-status-area-progress-outer').addClass('backup-progress-indeterminate');
|
|
$('#main-status-area-progress-bar').css('width', '0%');
|
|
} else {
|
|
$('#main-status-area-progress-outer').removeClass('backup-progress-indeterminate');
|
|
$('#main-status-area-progress-bar').css('width', parseInt(pg*100) + '%');
|
|
}
|
|
$('#main-status-area-progress-text').text(txt);
|
|
|
|
}
|
|
}
|
|
|
|
if (state.scheduled != null)
|
|
for(var n in state.scheduled)
|
|
if (scheduledMap['backup-' + state.scheduled[n].Item2] == null)
|
|
scheduledMap['backup-' + state.scheduled[n].Item2] = parseInt(n) + 1;
|
|
|
|
for(var n in PRIVATE_DATA.backup_list)
|
|
backupMap['backup-' + PRIVATE_DATA.backup_list[n].Backup.ID] = PRIVATE_DATA.backup_list[n];
|
|
|
|
$('#main-list').find('.main-backup-entry').each(function(i, e) {
|
|
var el = $(e);
|
|
|
|
if (isNaN($.parseDate(backupMap[e.id].Backup.Metadata.LastBackupStarted))) {
|
|
el.find('.last-run-time').hide();
|
|
} else {
|
|
el.find('.last-run-time').show();
|
|
}
|
|
|
|
// Scheduled items
|
|
if (scheduledMap[e.id]) {
|
|
el.find('.backup-next-run').text('#' + parseInt(scheduledMap[e.id]) + ' in queue');
|
|
el.find('.next-run-time').show();
|
|
} else if (e.id == current) {
|
|
el.find('.backup-next-run').text('Running now');
|
|
el.find('.next-run-time').show();
|
|
} else if (backupMap[e.id] && backupMap[e.id].Schedule) {
|
|
var targetDate = $.parseDate(backupMap[e.id].Schedule.Time);
|
|
el.find('.backup-next-run').text($.toDisplayDateAndTime(targetDate));
|
|
el.find('.next-run-time').show();
|
|
} else {
|
|
el.find('.next-run-time').hide();
|
|
}
|
|
});
|
|
};
|
|
|
|
PRIVATE_DATA.long_poll_for_status = function() {
|
|
var state = PRIVATE_DATA.server_state;
|
|
if (state.polling)
|
|
return;
|
|
|
|
if (state.retryTimer != null) {
|
|
$(document).trigger('server-state-connecting');
|
|
clearInterval(state.retryTimer);
|
|
state.retryTimer = null;
|
|
}
|
|
|
|
state.polling = true;
|
|
|
|
var req = { action: 'get-current-state', longpoll: true, lastEventId: state.eventId };
|
|
var timeout = 240000;
|
|
if (state.failed || state.eventId == -1) {
|
|
req.longpoll = false;
|
|
timeout = 5000
|
|
}
|
|
|
|
req.duration = parseInt((timeout-1000) / 1000) + 's';
|
|
|
|
$.ajax({
|
|
url: APP_CONFIG.server_url,
|
|
type: 'GET',
|
|
timeout: timeout,
|
|
dataType: 'json',
|
|
data: req
|
|
})
|
|
.done(function(data) {
|
|
state.polling = false;
|
|
state.state = data;
|
|
var oldDataId = state.dataEventId;
|
|
var oldState = state.programState;
|
|
var oldEventId = state.eventId;
|
|
|
|
state.eventId = data.LastEventID;
|
|
state.dataEventId = data.LastDataUpdateID;
|
|
state.programState = data.ProgramState;
|
|
state.scheduled = data.SchedulerQueueIds || [];
|
|
|
|
if (state.failed) {
|
|
state.failed = false;
|
|
|
|
// If the server was restarted, we refresh
|
|
if (oldEventId > state.eventId)
|
|
location.reload(true);
|
|
|
|
$(document).trigger('server-state-restored');
|
|
}
|
|
|
|
//If there is an active backup, (re)start the progress monitor
|
|
if (data.ActiveTask != null) {
|
|
state.activeTask = data.ActiveTask;
|
|
PRIVATE_DATA.poll_for_progress();
|
|
} else {
|
|
state.activeTask = null;
|
|
}
|
|
|
|
$(document).trigger('server-state-updated', data);
|
|
if (oldDataId != state.dataEventId)
|
|
$(document).trigger('server-state-data-updated', data);
|
|
|
|
if (oldState != state.programState) {
|
|
if (state.pauseUpdateTimer != null) {
|
|
clearInterval(state.pauseUpdateTimer);
|
|
state.pauseUpdateTimer = null;
|
|
}
|
|
|
|
$(document).trigger('server-state-changed', state.programState);
|
|
|
|
if (state.programState == 'Running') {
|
|
$(document).trigger('server-state-running');
|
|
} else if (state.programState == 'Paused') {
|
|
$(document).trigger('server-state-paused');
|
|
|
|
var estimatedEnd = Date.parse(data.EstimatedPauseEnd);
|
|
if (estimatedEnd > 0) {
|
|
estimatedEnd = new Date(estimatedEnd);
|
|
var updateTimer = function() {
|
|
var left = Math.max(0, estimatedEnd - new Date());
|
|
$(document).trigger('server-state-pause-countdown', {millisecondsLeft: left});
|
|
if (left == 0) {
|
|
clearInterval(state.pauseUpdateTimer);
|
|
state.pauseUpdateTimer = null;
|
|
}
|
|
|
|
}
|
|
|
|
state.pauseUpdateTimer = setInterval(updateTimer, 500);
|
|
updateTimer();
|
|
}
|
|
}
|
|
}
|
|
|
|
PRIVATE_DATA.update_progress_and_schedules();
|
|
PRIVATE_DATA.long_poll_for_status();
|
|
})
|
|
.fail(function(data) {
|
|
if (data.status == 401)
|
|
window.location = '/login.html';
|
|
|
|
state.polling = false;
|
|
if (!state.failed) {
|
|
state.failed = true;
|
|
$(document).trigger('server-state-lost');
|
|
}
|
|
|
|
state.retryStartTime = new Date();
|
|
var updateTimer = function() {
|
|
var n = new Date() - state.retryStartTime;
|
|
var left = Math.max(0, 15000 - n);
|
|
$(document).trigger('server-state-countdown', {millisecondsLeft: left});
|
|
if (left <= 0)
|
|
PRIVATE_DATA.long_poll_for_status();
|
|
}
|
|
|
|
state.retryTimer = setInterval(updateTimer, 500);
|
|
});
|
|
};
|
|
|
|
PRIVATE_DATA.server_progress = {
|
|
polling: false,
|
|
eventId: -1,
|
|
throttleTimer: null,
|
|
lastEvent: null,
|
|
updateFreq: 2000
|
|
};
|
|
|
|
PRIVATE_DATA.poll_for_progress = function() {
|
|
var state = PRIVATE_DATA.server_progress;
|
|
if (state.polling)
|
|
return;
|
|
|
|
if (state.throttleTimer != null) {
|
|
clearTimeout(state.throttleTimer);
|
|
state.throttleTimer = null;
|
|
}
|
|
|
|
state.polling = true;
|
|
|
|
var req = { action: 'get-progress-state', longpoll: false };
|
|
state.requestStart = new Date();
|
|
|
|
var restart_poll = function() {
|
|
if (state.throttleTimer != null) {
|
|
clearTimeout(state.throttleTimer);
|
|
state.throttleTimer = null;
|
|
}
|
|
|
|
var timeSinceLast = new Date() - state.requestStart;
|
|
if (timeSinceLast < state.updateFreq) {
|
|
state.throttleTimer = setTimeout(function(){
|
|
if (PRIVATE_DATA.server_state.activeTask != null)
|
|
PRIVATE_DATA.poll_for_progress();
|
|
|
|
}, Math.max(500, state.updateFreq - timeSinceLast));
|
|
} else {
|
|
if (PRIVATE_DATA.server_state.activeTask != null)
|
|
PRIVATE_DATA.poll_for_progress();
|
|
}
|
|
};
|
|
|
|
$.ajax({
|
|
url: APP_CONFIG.server_url,
|
|
type: 'GET',
|
|
timeout: 5000,
|
|
dataType: 'json',
|
|
data: req
|
|
})
|
|
.done(function(data) {
|
|
state.polling = false;
|
|
state.eventId = data.LastEventID;
|
|
state.lastEvent = data;
|
|
PRIVATE_DATA.update_progress_and_schedules();
|
|
|
|
$(document).trigger('server-progress-updated', data);
|
|
|
|
restart_poll();
|
|
})
|
|
.fail(function(data, a, b, c, d) {
|
|
state.polling = false;
|
|
if (PRIVATE_DATA.server_state.failed) {
|
|
// We will be restarted on re-connect
|
|
} else {
|
|
// Bad poll request, just retry
|
|
restart_poll();
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
PRIVATE_DATA.refresh_server_settings = function(callback, errorhandler) {
|
|
serverWithCallback(
|
|
'system-info',
|
|
callback,
|
|
errorhandler,
|
|
function(data, success) {
|
|
if (success && data != null) {
|
|
PRIVATE_DATA.server_config = data;
|
|
window.document.title = APP_CONFIG.branded_name + ' - ' + data.MachineName;
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
PRIVATE_DATA.refresh_backup_list = function(callback, errorhandler) {
|
|
serverWithCallback(
|
|
'list-backups',
|
|
callback,
|
|
errorhandler,
|
|
function(data, success) {
|
|
if (success && data != null) {
|
|
PRIVATE_DATA.backup_list = data;
|
|
|
|
// Clear existing stuff
|
|
$('#main-list-container > div.main-backup-entry').remove();
|
|
|
|
if ($('#backup-item-template').length > 0 && data.length > 0) {
|
|
|
|
// Pre-processing of data
|
|
for(var n in data)
|
|
data[n].Backup.Metadata = data[n].Backup.Metadata || {};
|
|
|
|
if (APP_DATA.plugins.primary['backup-list-preprocess'])
|
|
APP_DATA.plugins.primary['backup-list-preprocess'](data);
|
|
|
|
//Fill with jQuery template
|
|
$.tmpl($('#backup-item-template'), data).prependTo($('#main-list-container'));
|
|
|
|
var decodeid = function(e) {
|
|
var p = e.delegateTarget.id.split('-');
|
|
return parseInt(p[p.length - 1]);
|
|
};
|
|
|
|
// Post processing of data
|
|
for(var n in data) {
|
|
var id = data[n].Backup.ID;
|
|
|
|
// Setup context menu trigger
|
|
$('#backup-control-' + id).click(function(e) {
|
|
var id = decodeid(e);
|
|
APP_DATA.showContextMenu(id, $('#backup-control-' + id));
|
|
});
|
|
}
|
|
|
|
if (APP_DATA.plugins.primary['backup-list-postrocess'])
|
|
APP_DATA.plugins.primary['backup-list-postrocess']($('#main-list-container'), $('#main-list-container > div.main-backup-entry'), data);
|
|
}
|
|
}
|
|
|
|
PRIVATE_DATA.update_progress_and_schedules();
|
|
}
|
|
);
|
|
};
|
|
|
|
APP_DATA.getBackupName = function(id) {
|
|
if (PRIVATE_DATA.backup_list)
|
|
for(var n in PRIVATE_DATA.backup_list)
|
|
if (PRIVATE_DATA.backup_list[n].Backup.ID == id)
|
|
return PRIVATE_DATA.backup_list[n].Backup.Name;
|
|
return null;
|
|
};
|
|
|
|
APP_DATA.getServerConfig = function(callback, errorhandler) {
|
|
if (PRIVATE_DATA.server_config == null) {
|
|
PRIVATE_DATA.refresh_server_settings(callback, errorhandler);
|
|
} else {
|
|
callback(PRIVATE_DATA.server_config);
|
|
}
|
|
};
|
|
|
|
APP_DATA.validatePath = function(path, callback) {
|
|
serverWithCallback({ action: 'validate-path', path: path }, callback, callback);
|
|
};
|
|
APP_DATA.getLabels = function(callback) {
|
|
serverWithCallback('list-tags', callback, callback);
|
|
};
|
|
|
|
APP_DATA.getBackupDefaults = function(callback, errorhandler) {
|
|
serverWithCallback('get-backup-defaults', callback, errorhandler);
|
|
};
|
|
APP_DATA.getBackupData = function(id, callback, errorhandler) {
|
|
serverWithCallback({ action: 'get-backup', id: id}, callback, errorhandler);
|
|
};
|
|
|
|
APP_DATA.addBackup = function(cfg, callback, errorhandler, extra_options) {
|
|
serverWithCallback(
|
|
$.extend(
|
|
{},
|
|
extra_options,
|
|
{ action: 'add-backup', HTTP_METHOD: 'POST', data: JSON.stringify(cfg)}
|
|
),
|
|
callback,
|
|
errorhandler
|
|
);
|
|
};
|
|
|
|
APP_DATA.updateBackup = function(cfg, callback, errorhandler) {
|
|
serverWithCallback(
|
|
{ action: 'update-backup', HTTP_METHOD: 'POST', data: JSON.stringify(cfg)},
|
|
callback,
|
|
errorhandler
|
|
);
|
|
};
|
|
|
|
APP_DATA.locateUriDb = function(targeturl, callback, errorhandler) {
|
|
serverWithCallback(
|
|
{ action: 'locate-uri-db', HTTP_METHOD: 'POST', uri: targeturl},
|
|
callback,
|
|
errorhandler
|
|
);
|
|
};
|
|
|
|
APP_DATA.editNewBackup = function() {
|
|
APP_DATA.editBackup();
|
|
};
|
|
|
|
APP_DATA.deleteBackup = function(id, callback, errorhandler) {
|
|
serverWithCallback(
|
|
{ action: 'delete-backup', id: id },
|
|
callback,
|
|
errorhandler
|
|
);
|
|
};
|
|
|
|
APP_DATA.editBackup = function(id) {
|
|
APP_DATA.getServerConfig(function(data) {
|
|
|
|
var callback = function(data) {
|
|
$("#edit-dialog").dialog('open');
|
|
|
|
// Bug-fix, this will remove style="width: auto", which breaks Chrome a bit
|
|
$("#edit-dialog").css('width', '');
|
|
|
|
// Send data to the dialog
|
|
$("#edit-dialog").trigger('setup-dialog', data.data);
|
|
};
|
|
|
|
var errorhandler = function() {
|
|
alert('Failed to get server setup...')
|
|
};
|
|
|
|
if (id == undefined || parseInt(id) < 0)
|
|
APP_DATA.getBackupDefaults(callback, errorhandler);
|
|
else
|
|
APP_DATA.getBackupData(id, callback, errorhandler);
|
|
},
|
|
function() {
|
|
alert('Failed to get server setup...')
|
|
});
|
|
|
|
};
|
|
|
|
APP_DATA.runBackup = function(id) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'run-backup', id: id },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to start backup: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.isBackupActive = function(id, callback) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'is-backup-active', id: id },
|
|
function(data) { callback(data.Active); },
|
|
function(d,s,m) { alert('Failed to query backup: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.restoreBackup = function(id) {
|
|
APP_DATA.isBackupActive(id, function(active) {
|
|
if (active) {
|
|
alert('Cannot start restore while the backup is active.');
|
|
} else {
|
|
$('#restore-dialog').dialog('open');
|
|
$('#restore-dialog').trigger('setup-data', id);
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
APP_DATA.pauseServer = function(duration) {
|
|
serverWithCallback({action: 'send-command', command: 'pause', duration: duration});
|
|
};
|
|
|
|
APP_DATA.resumeServer = function() {
|
|
serverWithCallback({action: 'send-command', command: 'resume'});
|
|
};
|
|
|
|
APP_DATA.stopTask = function(taskId, force) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: force ? 'abort' : 'stop', taskid: taskId },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to send stop command: ' + m); }
|
|
);
|
|
}
|
|
|
|
APP_DATA.runVerify = function(id) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'run-verify', id: id },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to start verification: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.runRepair = function(id) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'run-repair', id: id },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to start repair: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.createReport = function(id) {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'create-report', id: id },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to create bug report: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.hasLoadedAbout = false;
|
|
|
|
APP_DATA.showAbout = function() {
|
|
|
|
var licenses = {
|
|
'MIT': 'http://www.linfo.org/mitlicense.html',
|
|
'Apache': 'https://www.apache.org/licenses/LICENSE-2.0.html',
|
|
'Apache 2': 'https://www.apache.org/licenses/LICENSE-2.0.html',
|
|
'Apache 2.0': 'https://www.apache.org/licenses/LICENSE-2.0.html',
|
|
'Public Domain': 'https://creativecommons.org/licenses/publicdomain/',
|
|
'GPL': 'https://www.gnu.org/copyleft/gpl.html',
|
|
'LGPL': 'https://www.gnu.org/copyleft/lgpl.html',
|
|
'MS-PL': 'http://opensource.org/licenses/MS-PL',
|
|
'Microsoft Public': 'http://opensource.org/licenses/MS-PL',
|
|
'New BSD': 'http://opensource.org/licenses/BSD-3-Clause'
|
|
};
|
|
|
|
if (!APP_DATA.hasLoadedAbout) {
|
|
serverWithCallback('get-license-data',
|
|
function(data) {
|
|
var d = [];
|
|
for(var n in data) {
|
|
try {
|
|
var r = JSON.parse(data[n].Jsondata);
|
|
if (r != null) {
|
|
r.licenselink = r.licenselink || licenses[r.license] || '#';
|
|
d.push(r);
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
$('#about-dialog-current-version').text(PRIVATE_DATA.server_config.ServerVersionName);
|
|
|
|
$('#about-dialog-thirdparty-list').empty();
|
|
$('#about-dialog-thirdparty-list').append($.tmpl($('#about-dialog-template'), d));
|
|
APP_DATA.hasLoadedAbout = true;
|
|
APP_DATA.showAbout();
|
|
}, function(msg) {
|
|
alert('Failed to load data: ' + msg);
|
|
});
|
|
} else {
|
|
$('#about-dialog').dialog('open');
|
|
}
|
|
};
|
|
|
|
APP_DATA.checkForUpdates = function() {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'check-update' },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to check for updates: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.installUpdate = function() {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'install-update' },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to install for update: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.activateUpdate = function() {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'activate-update' },
|
|
function() {},
|
|
function(d,s,m) { alert('Failed to activate update: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.postponeUpdate = function() {
|
|
serverWithCallback(
|
|
{ action: 'send-command', command: 'postpone-update' },
|
|
function() {},
|
|
function() {}
|
|
);
|
|
};
|
|
|
|
APP_DATA.showChangelog = function(from_update) {
|
|
serverWithCallback(
|
|
{ action: 'get-changelog', 'from-update': from_update ? 'true' : '' },
|
|
function(data) {
|
|
var dlg = $('<div></div>').attr('title', 'Changelog');
|
|
|
|
var pgtxt = $('<pre></pre>');
|
|
pgtxt.text(data.Changelog);
|
|
dlg.append(pgtxt);
|
|
|
|
dlg.dialog({
|
|
autoOpen: true,
|
|
width: $('body').width > 450 ? 430 : 600,
|
|
height: 500,
|
|
modal: true,
|
|
closeOnEscape: true,
|
|
buttons: [
|
|
{ text: 'Close', click: function(event, ui) {
|
|
dlg.dialog('close');
|
|
dlg.remove();
|
|
}}
|
|
]
|
|
});
|
|
|
|
},
|
|
function(d,s,m) { alert('Failed to get changelog: ' + m); }
|
|
);
|
|
};
|
|
|
|
APP_DATA.callServer = serverWithCallback;
|
|
|
|
$.showPopupMenu = function(menu, anchor, offset) {
|
|
var pos = anchor.offset();
|
|
var menuwidth = menu.outerWidth();
|
|
var menuheight = menu.outerHeight();
|
|
|
|
offset = offset || {};
|
|
offset.x = offset.x || 0;
|
|
offset.y = offset.y || 0;
|
|
|
|
menu.toggle();
|
|
|
|
var left = pos.left + offset.x;
|
|
var top = pos.top + offset.y;
|
|
if (left + menuwidth > $(document).outerWidth())
|
|
left -= menuwidth;
|
|
if (top + menuheight > $(document).outerHeight())
|
|
top -= menuheight;
|
|
|
|
if (menu.is(':visible')) {
|
|
menu.css({
|
|
position: 'absolute',
|
|
top: top + 'px',
|
|
left: left + 'px'
|
|
});
|
|
$('#click-intercept').show();
|
|
}
|
|
};
|
|
|
|
$('#main-settings').click(function() {
|
|
var pos = $('#main-settings').offset();
|
|
var buttonwidth = $('#main-settings').outerWidth();
|
|
$.showPopupMenu($('#main-control-menu'), $('#main-settings'), {y: $('#main-topbar').outerHeight() - pos.top });
|
|
|
|
$('#main-control-menu').css({ left: "", right: ($(document).outerWidth() - (pos.left + buttonwidth)) + 'px' });
|
|
});
|
|
|
|
$('#click-intercept').click(function() {
|
|
$('#click-intercept').hide();
|
|
$('.menu').hide();
|
|
});
|
|
|
|
$('#main-donate').click(function() {
|
|
|
|
});
|
|
|
|
$('#main-control').click(function() {
|
|
});
|
|
|
|
$('#main-newbackup').click(function() {
|
|
APP_DATA.editNewBackup();
|
|
|
|
});
|
|
|
|
$('#edit-dialog').tabs({ active: 0 });
|
|
$('#edit-dialog').dialog({
|
|
minWidth: 320,
|
|
width: $('body').width > 600 ? 320 : 600,
|
|
minHeight: 480,
|
|
height: 500,
|
|
modal: true,
|
|
autoOpen: false,
|
|
closeOnEscape: true,
|
|
buttons: [
|
|
{ text: '< Previous', disabled: true, click: function(event, ui) {
|
|
var cur = parseInt($('#edit-dialog').tabs( "option", "active"));
|
|
cur = Math.max(cur-1, 0);
|
|
$('#edit-dialog').tabs( "option", "active", cur);
|
|
}},
|
|
{ text: 'Next >', click: function(event, ui) {
|
|
var cur = parseInt($('#edit-dialog').tabs( "option", "active"));
|
|
var max = $('#edit-dialog').parent().find('[role=tablist] > li').size() - 1;
|
|
|
|
if (!EDIT_BACKUP.validate_tab(cur))
|
|
return;
|
|
|
|
event.curPage = cur;
|
|
event.currentTarget.curPage = cur;
|
|
cur = Math.min(cur+1, max);
|
|
$('#edit-dialog').tabs( "option", "active", cur);
|
|
}}
|
|
]
|
|
});
|
|
|
|
$(document).on('server-state-updated', function() {
|
|
$('#loading-dialog').dialog("close");
|
|
});
|
|
|
|
$(document).on('server-state-lost', function() {
|
|
$('#connection-lost-dialog').dialog('open');
|
|
$('#connection-lost-dialog-text').text('Server connection lost...');
|
|
var button = $('#connection-lost-dialog').parent().find('.ui-dialog-buttonpane').find('.ui-button').first();
|
|
button.attr("disabled",false).removeClass( 'ui-button-disabled ui-state-disabled' );
|
|
|
|
});
|
|
|
|
$(document).on('server-state-restored', function() {
|
|
$('#connection-lost-dialog').dialog('close');
|
|
});
|
|
|
|
$(document).on('server-state-countdown', function(e, f) {
|
|
var s = parseInt(f.millisecondsLeft / 1000) + 1;
|
|
$('#connection-lost-dialog-text').html('Server connection lost, <br/>retry in ' + s + ' seconds');
|
|
var button = $('#connection-lost-dialog').parent().find('.ui-dialog-buttonpane').find('.ui-button').first();
|
|
button.attr("disabled",false).removeClass( 'ui-button-disabled ui-state-disabled' );
|
|
});
|
|
|
|
$(document).on('server-state-connecting', function(e) {
|
|
$('#connection-lost-dialog-text').text('Retrying...');
|
|
var button = $('#connection-lost-dialog').parent().find('.ui-dialog-buttonpane').find('.ui-button').first();
|
|
button.attr("disabled",true).addClass( 'ui-button-disabled ui-state-disabled' );
|
|
});
|
|
|
|
$(document).on('server-state-running', function() {
|
|
$('#main-control').removeClass('main-icon-run').addClass('main-icon-pause');
|
|
});
|
|
|
|
$(document).on('server-state-paused', function() {
|
|
$('#main-control').removeClass('main-icon-pause').addClass('main-icon-run');
|
|
});
|
|
|
|
$(document).on('server-state-pause-countdown', function(e, f) {
|
|
var s = parseInt(f.millisecondsLeft / 1000) + 1;
|
|
});
|
|
|
|
$('#main-control').click(function() {
|
|
if ($('#main-control').hasClass('main-icon-run'))
|
|
APP_DATA.resumeServer();
|
|
else
|
|
APP_DATA.pauseServer();
|
|
});
|
|
|
|
$('#connection-lost-dialog').dialog({
|
|
modal: true,
|
|
autoOpen: false,
|
|
closeOnEscape: false,
|
|
buttons: [
|
|
{
|
|
text: 'Retry now',
|
|
disabled: true,
|
|
click: function(event, ui) {
|
|
PRIVATE_DATA.long_poll_for_status();
|
|
}
|
|
}
|
|
]
|
|
});
|
|
|
|
$('#connection-lost-dialog').parent().find('.ui-dialog-titlebar-close').remove().first().remove();
|
|
|
|
$('#connection-lost-dialog').on('dialogbeforeclose', function( event, ui ) {
|
|
return !PRIVATE_DATA.server_state.failed;
|
|
});
|
|
|
|
|
|
$(document).on('server-state-data-updated', function() {
|
|
PRIVATE_DATA.refresh_backup_list();
|
|
});
|
|
|
|
PRIVATE_DATA.long_poll_for_status();
|
|
PRIVATE_DATA.refresh_server_settings();
|
|
PRIVATE_DATA.refresh_backup_list();
|
|
|
|
$('#main-control-menu').menu();
|
|
$('#main-control-menu').removeClass('ui-widget-content');
|
|
$('#main-control-menu-pause-submenu').removeClass('ui-widget-content');
|
|
$('#main-control-menu-settings').hide().next().hide();
|
|
$('#main-control-menu-throttle').hide();
|
|
|
|
$('#main-control-menu-about').click(function() { APP_DATA.showAbout(); })
|
|
|
|
$('#main-control-menu-pause-submenu-5m').click(function() { APP_DATA.pauseServer('5m'); });
|
|
$('#main-control-menu-pause-submenu-10m').click(function() { APP_DATA.pauseServer('10m'); });
|
|
$('#main-control-menu-pause-submenu-15m').click(function() { APP_DATA.pauseServer('15m'); });
|
|
$('#main-control-menu-pause-submenu-30m').click(function() { APP_DATA.pauseServer('30m'); });
|
|
$('#main-control-menu-pause-submenu-1h').click(function() { APP_DATA.pauseServer('1h'); });
|
|
|
|
var updaterState = {
|
|
state: 'Waiting',
|
|
version: null,
|
|
installed: false,
|
|
restarted: false,
|
|
simplestate: null,
|
|
noty: null,
|
|
noty_type: null,
|
|
|
|
closeNoty: function() {
|
|
if (this.noty != null) {
|
|
this.noty.close();
|
|
this.noty = null;
|
|
this.noty_type = null;
|
|
}
|
|
},
|
|
checkingNoty: function() {
|
|
this.closeNoty();
|
|
this.noty = noty({
|
|
text: 'Checking for updates ...',
|
|
});
|
|
this.noty_type = 'checking';
|
|
},
|
|
downloadingNoty: function() {
|
|
this.closeNoty();
|
|
var self = this;
|
|
this.noty = noty({
|
|
text: 'Downloading update ' + self.version,
|
|
});
|
|
this.noty_type = 'downloading';
|
|
},
|
|
setDownloadProgress: function(pg) {
|
|
if (this.noty_type == 'downloading' && this.noty != null)
|
|
this.noty.setText('Downloading update ' + this.version + ' (' + parseInt(pg*100) + '%)');
|
|
|
|
},
|
|
foundupdateNoty: function() {
|
|
this.closeNoty();
|
|
var self = this;
|
|
this.noty = noty({
|
|
text: 'Found update <div class="noty-update-changelog-link">' + self.version + '</div>',
|
|
buttons: [{
|
|
text: 'Not now',
|
|
onClick: function() {
|
|
APP_DATA.postponeUpdate();
|
|
self.closeNoty();
|
|
}
|
|
},{
|
|
text: 'Update',
|
|
onClick: function() {
|
|
APP_DATA.installUpdate();
|
|
}
|
|
}]
|
|
});
|
|
this.noty_type = 'found';
|
|
$('.noty-update-changelog-link').click(function() { APP_DATA.showChangelog(true); });
|
|
},
|
|
updateinstalledNoty: function() {
|
|
this.closeNoty();
|
|
var self = this;
|
|
this.noty = noty({
|
|
text: 'Update <div class="noty-update-changelog-link">' + self.version + '</div> installed',
|
|
buttons: [{
|
|
text: 'Not now',
|
|
onClick: function() {
|
|
self.closeNoty();
|
|
}
|
|
},{
|
|
text: 'Restart',
|
|
onClick: function() {
|
|
self.activateUpdate();
|
|
self.closeNoty();
|
|
}
|
|
}]
|
|
});
|
|
this.noty_type = 'installed';
|
|
$('.noty-update-changelog-link').click(function() { APP_DATA.showChangelog(true); });
|
|
},
|
|
activateUpdate: function() {
|
|
if (confirm('Restart ' + APP_CONFIG.branded_name + ' and activate update?'))
|
|
{
|
|
APP_DATA.activateUpdate();
|
|
updaterState.restarted = true;
|
|
}
|
|
},
|
|
noUpdatesNoty: function() {
|
|
noty({
|
|
text: 'No updates found',
|
|
timeout: 5000
|
|
});
|
|
}
|
|
};
|
|
|
|
$(document).on('server-state-updated', function(eventargs, data) {
|
|
var prevstate = updaterState.simplestate;
|
|
|
|
updaterState.state = data.UpdaterState;
|
|
updaterState.version = data.UpdatedVersion;
|
|
updaterState.installed = data.UpdateReady;
|
|
|
|
if (updaterState.restarted && updaterState.version == null)
|
|
location.reload(true);
|
|
|
|
if (updaterState.state == 'Waiting') {
|
|
if (updaterState.version == null)
|
|
updaterState.simplestate = null;
|
|
else if (!updaterState.installed)
|
|
updaterState.simplestate = 'found';
|
|
else if (updaterState.installed)
|
|
updaterState.simplestate = 'installed';
|
|
else
|
|
updaterState.simplestate = null;
|
|
|
|
} else if (updaterState.state == 'Checking') {
|
|
updaterState.simplestate = 'check';
|
|
} else if (updaterState.state == 'Downloading') {
|
|
updaterState.simplestate = 'download';
|
|
} else {
|
|
updaterState.simplestate = null;
|
|
}
|
|
|
|
if (updaterState.simplestate == null) {
|
|
$('#main-control-menu-updates > a').text('Check for updates');
|
|
$('#main-control-menu-updates').removeClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').hide();
|
|
} else if (updaterState.simplestate == 'found') {
|
|
$('#main-control-menu-updates > a').text('Install update');
|
|
$('#main-control-menu-updates').removeClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').show();
|
|
} else if (updaterState.simplestate == 'installed') {
|
|
$('#main-control-menu-updates > a').text('Restart with update');
|
|
$('#main-control-menu-updates').removeClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').hide();
|
|
} else if (updaterState.simplestate == 'check') {
|
|
$('#main-control-menu-updates > a').text('Checking for update ...');
|
|
$('#main-control-menu-updates').addClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').hide();
|
|
} else if (updaterState.simplestate == 'download') {
|
|
$('#main-control-menu-updates > a').text('Downloading update ...');
|
|
$('#main-control-menu-updates').addClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').hide();
|
|
} else {
|
|
$('#main-control-menu-updates > a').text('Unknown state ...');
|
|
$('#main-control-menu-updates').addClass('ui-state-disabled');
|
|
$('#main-control-menu-check-updates').show();
|
|
}
|
|
|
|
if (updaterState.simplestate != prevstate) {
|
|
if (updaterState.simplestate == 'found')
|
|
updaterState.foundupdateNoty();
|
|
else if (updaterState.simplestate == 'installed')
|
|
updaterState.updateinstalledNoty();
|
|
else if (updaterState.simplestate == 'check')
|
|
updaterState.checkingNoty();
|
|
else if (updaterState.simplestate == 'download')
|
|
updaterState.downloadingNoty();
|
|
else
|
|
{
|
|
updaterState.closeNoty();
|
|
if (prevstate == 'check')
|
|
updaterState.noUpdatesNoty();
|
|
}
|
|
} else if (updaterState.simplestate == 'download') {
|
|
updaterState.setDownloadProgress(data.UpdateDownloadProgress);
|
|
}
|
|
|
|
});
|
|
|
|
$('#main-control-menu-check-updates').click(function() {
|
|
if (updaterState.state != 'Waiting')
|
|
return;
|
|
|
|
APP_DATA.checkForUpdates();
|
|
});
|
|
|
|
$('#main-control-menu-updates').click(function() {
|
|
if (updaterState.state != 'Waiting')
|
|
return;
|
|
|
|
if (updaterState.version == null) {
|
|
APP_DATA.checkForUpdates();
|
|
} else if (!updaterState.installed) {
|
|
APP_DATA.checkForUpdates();
|
|
APP_DATA.installUpdate();
|
|
} else if (updaterState.installed) {
|
|
updaterState.activateUpdate();
|
|
}
|
|
});
|
|
|
|
$('#main-control-menu-log').click(function() { $.showAppLog(); });
|
|
|
|
$('#main-control-menu').find('li').click(function() { $('#click-intercept').trigger('click'); });
|
|
|
|
var pausenoty = {
|
|
n: null,
|
|
prevstate: null
|
|
};
|
|
|
|
$(document).on('server-state-changed', function(e, state) {
|
|
if (pausenoty.prevstate != state && pausenoty.prevstate != null) {
|
|
if (pausenoty.n != null)
|
|
pausenoty.n.close();
|
|
|
|
if (state == 'Running') {
|
|
pausenoty.n = noty({
|
|
text: 'Server is now resumed',
|
|
timeout: 5000
|
|
});
|
|
} else {
|
|
pausenoty.n = noty({
|
|
text: 'Server is paused',
|
|
buttons: [{
|
|
text: 'Resume',
|
|
onClick: function() {
|
|
APP_DATA.resumeServer();
|
|
}
|
|
}]
|
|
});
|
|
}
|
|
}
|
|
|
|
pausenoty.prevstate = state;
|
|
});
|
|
|
|
$(document).on('server-state-pause-countdown', function(e, data) {
|
|
if (pausenoty.prevstate != 'Paused' || pausenoty.n == null) {
|
|
if (pausenoty.n != null)
|
|
pausenoty.n.close();
|
|
pausenoty.n = noty({
|
|
text: 'Server is paused',
|
|
buttons: [{
|
|
text: 'Resume',
|
|
onClick: function() {
|
|
APP_DATA.resumeServer();
|
|
}
|
|
}]
|
|
});
|
|
}
|
|
var seconds = parseInt(data.millisecondsLeft / 1000);
|
|
var hours = parseInt(seconds / 3600);
|
|
seconds -= (hours * 3600);
|
|
var minutes = parseInt(seconds / 60)
|
|
seconds -= (minutes * 60);
|
|
seconds = seconds + '';
|
|
if (seconds.length == 1)
|
|
seconds = '0' + seconds;
|
|
|
|
var timestr = '';
|
|
if (hours > 0)
|
|
timestr += hours + 'h ';
|
|
|
|
timestr += minutes + ':' + seconds;
|
|
|
|
pausenoty.n.setText('Server is paused, resuming in ' + timestr);
|
|
});
|
|
|
|
$("#about-dialog").dialog({
|
|
minWidth: 320,
|
|
width: $('body').width > 600 ? 320 : 600,
|
|
minHeight: 480,
|
|
height: 500,
|
|
modal: true,
|
|
autoOpen: false,
|
|
closeOnEscape: true,
|
|
buttons: [
|
|
{ text: 'Close', disabled: false, click: function(event, ui) {
|
|
$('#about-dialog').dialog('close');
|
|
}}
|
|
]
|
|
});
|
|
|
|
$('#about-dialog-changelog').click(function() { APP_DATA.showChangelog(false); });
|
|
|
|
setInterval(function() {
|
|
$('#main-list').find('.backup-last-run').each(function(i, e) {
|
|
$(e).text($.timeago($.parseDate($(e).attr('alt'))));
|
|
})
|
|
}, 60*1000);
|
|
|
|
APP_DATA.getCurrentBackupId = function() {
|
|
return PRIVATE_DATA.server_state.activeTask == null ? null : PRIVATE_DATA.server_state.activeTask.Item2;
|
|
};
|
|
|
|
APP_DATA.getCurrentTaskId = function() {
|
|
return PRIVATE_DATA.server_state.activeTask == null ? null : PRIVATE_DATA.server_state.activeTask.Item1;
|
|
};
|
|
|
|
APP_DATA.contextMenuId = null;
|
|
APP_DATA.showContextMenu = function(id, anchor) {
|
|
APP_DATA.contextMenuId = id;
|
|
$.showPopupMenu($('#backup-context-menu'), anchor, {x: $(anchor).outerWidth() + 10});
|
|
};
|
|
|
|
$('#backup-details-run').click(function(e) {
|
|
APP_DATA.runBackup(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-restore').click(function(e) {
|
|
APP_DATA.restoreBackup(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-edit').click(function(e) {
|
|
APP_DATA.editBackup(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-delete').click(function(e) {
|
|
var name = APP_DATA.getBackupName(APP_DATA.contextMenuId);
|
|
|
|
if (name && confirm('Really delete ' + name + '?'))
|
|
APP_DATA.deleteBackup(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-show-log').click(function(e) {
|
|
$.showBackupLog(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-verify').click(function(e) {
|
|
APP_DATA.runVerify(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-send-report').click(function(e) {
|
|
alert('Method is missing a method for retrieving the report after it has been generated');
|
|
APP_DATA.createReport(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-repair').click(function(e) {
|
|
APP_DATA.runRepair(APP_DATA.contextMenuId);
|
|
});
|
|
|
|
$('#backup-details-copy').click(function(e) {
|
|
alert('Function is not implemented yet');
|
|
});
|
|
|
|
$('#backup-details-delete-local').click(function(e) {
|
|
alert('Function is not implemented yet');
|
|
});
|
|
|
|
$('#backup-details-delete-remote').click(function(e) {
|
|
alert('Function is not implemented yet');
|
|
});
|
|
|
|
$('#backup-context-menu').menu().removeClass('ui-widget-content');
|
|
$('#backup-context-menu').find('li').click(function() { $('#click-intercept').trigger('click'); });
|
|
|
|
|
|
var cancelnoty = {
|
|
n: null,
|
|
taskId: null,
|
|
onRequest: function() {
|
|
var current = APP_DATA.getCurrentTaskId();
|
|
|
|
if (current == null)
|
|
return;
|
|
|
|
// Seems too harsh to use the double-stop = force logic
|
|
/*if (this.cancel_task_id == current) {
|
|
APP_DATA.stopTask(current, true);
|
|
} else*/ {
|
|
APP_DATA.stopTask(current, false);
|
|
if (this.cancel_task_id != current) {
|
|
this.cancel_task_id = current;
|
|
|
|
if (this.n != null) {
|
|
this.n.close();
|
|
this.n = null;
|
|
}
|
|
|
|
this.n = noty({
|
|
text: 'Task stopped, waiting for task to clean up',
|
|
buttons: [{
|
|
text: 'Force stop',
|
|
onClick: function() {
|
|
APP_DATA.stopTask(current, true);
|
|
}
|
|
}]
|
|
});
|
|
}
|
|
}
|
|
},
|
|
onUpdate: function() {
|
|
if (this.n == null)
|
|
return;
|
|
|
|
var current = APP_DATA.getCurrentTaskId();
|
|
if (current != this.cancel_task_id) {
|
|
this.n.close();
|
|
this.n = null;
|
|
this.cancel_task_id = null;
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
|
|
$(document).on('server-state-updated', function(e, data) {
|
|
cancelnoty.onUpdate();
|
|
});
|
|
|
|
$(document).on('server-progress-updated', function(e, data) {
|
|
cancelnoty.onUpdate();
|
|
});
|
|
|
|
$('#main-status-area-cancel-button').click(function() {
|
|
var dlg = $('<div></div>').attr('title', 'Warning');
|
|
dlg.dialog({
|
|
autoOpen: true,
|
|
width: $('body').width > 450 ? 430 : 600,
|
|
modal: true,
|
|
closeOnEscape: true,
|
|
buttons: [
|
|
{ text: 'Stop now', click: function(event, ui) {
|
|
var current = APP_DATA.getCurrentTaskId();
|
|
if (current != null)
|
|
APP_DATA.stopTask(current, true);
|
|
|
|
dlg.dialog('close');
|
|
dlg.remove();
|
|
}},
|
|
{ text: 'Stop after upload', click: function(event, ui) {
|
|
cancelnoty.onRequest();
|
|
dlg.dialog('close');
|
|
dlg.remove();
|
|
}},
|
|
{ text: 'Cancel', click: function(event, ui) {
|
|
dlg.dialog('close');
|
|
dlg.remove();
|
|
}}
|
|
]
|
|
});
|
|
|
|
var pgtxt = $('<div></div>');
|
|
pgtxt.text('Stop the current task?');
|
|
dlg.append(pgtxt);
|
|
|
|
});
|
|
|
|
}); |