Some work on the status window

git-svn-id: https://duplicati.googlecode.com/svn/trunk@1273 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
kenneth@hexad.dk
2012-05-14 18:46:45 +00:00
parent 20c3dcd8e5
commit 433d709be6
6 changed files with 326 additions and 106 deletions
@@ -19,8 +19,16 @@
}
else
return v || false;
}
};
APP_SCOPE.toJsDate = function(str) {
if (str == null)
return null;
var strtmp = str.replace(/\/Date\((-?\d+(((\+|\-)\d+)|Z|z)?)\)\//gi, "new Date($1)");
return eval(strtmp);
};
APP_SCOPE.createHtmlItems = function(html) {
if (ls.creator_div == null) {
ls.creator_div = document.createElement("div");
@@ -44,23 +52,17 @@
}
};
APP_SCOPE.applyRoundedCornerClass = function() {
$('.rounded-corner-box').each(function(index, el) {
if (!$(el).hasClass('created-round-corner-box')) {
$(el).removeClass('rounded-corner-box');
var x = el.innerHTML;
el.innerHTML = '<table class="round-corner-box created-round-corner-box"><tr class="top"><td class="left"></td><td class="middle"></td><td class="right"></td></tr><tr class="center"><td class="left"></td><td class="middle">' + x + '</div></td><td class="right"></td></tr><tr class="bottom"><td class="left"></td><td class="middle"></td><td class="right"></td></tr></table>';
}
});
}
APP_SCOPE.getActionUrl = function(action) {
//During the design phase, we emulate the server with a folder
//return './server-responses/' + encodeURIComponent(action) + '.txt';
return APP_SCOPE.ServerURL + 'control.cgi?action=' + encodeURIComponent(action);
}
APP_SCOPE.getCurrentState = function(callback) {
$.getJSON(this.getActionUrl('get-current-state'), callback);
};
APP_SCOPE.getApplicationSettings = function(callback) {
$.getJSON(this.getActionUrl('list-application-settings'), callback);
};
@@ -83,7 +85,7 @@
callback(APP_SCOPE.CompressionModules);
}
};
APP_SCOPE.getInstalledGenericModules = function(callback) {
if (APP_SCOPE.CompressionModules == null) {
$.getJSON(this.getActionUrl('list-installed-generic-modules'), function(resp) {
@@ -119,7 +121,21 @@
};
$(document).ready(function(){
if (window.external && window.external.AddSearch == null && window.external.AddSearchProvider == null) {
ads = null;
adsp = null;
extmin = null;
if (window.external)
{
try { ads = window.external.AddSearch; }
catch (e) {}
try { adsp = window.external.AddSearchProvider; }
catch (e) {}
try { extmin = window.external.setMinSiz; }
catch (e) {}
}
if (window.external && ads == null && adsp == null && extmin != null) {
APP_SCOPE.external = window.external;
APP_SCOPE.activateFunction = function(code) {
APP_SCOPE.external.openWindow(code);
@@ -129,8 +145,6 @@
alert("Unimplemented " + code);
}
}
APP_SCOPE.applyRoundedCornerClass();
});
})();
@@ -0,0 +1,150 @@
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 0.11.2
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ago",
suffixFromNow: "from now",
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: " ",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 42 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.round(days)) ||
days < 45 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
years < 1.5 && substitute($l.year, 1) ||
substitute($l.years, Math.round(years));
var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator;
return $.trim([prefix, words, suffix].join(separator));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
},
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
}
});
$.fn.timeago = function() {
var self = this;
self.each(refresh);
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(function() { self.each(refresh); }, $s.refreshMillis);
}
return self;
};
function refresh() {
var data = prepareData(this);
if (!isNaN(data.datetime)) {
$(this).text(inWords(data.datetime));
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}(jQuery));
@@ -1,8 +1,8 @@
$(document).ready(function(){
APP_SCOPE.applyRoundedCornerClass();
$('#appname').each(function(i, e) { e.innerHTML = APP_SCOPE.AppName;});
jQuery.timeago.settings.allowFuture = true;
//Request some initial data for making the display
// we execute these in parallel for efficiency
APP_SCOPE.getApplicationSettings(function(data) {
@@ -14,21 +14,49 @@ $(document).ready(function(){
APP_SCOPE.backupSchedules = data;
APP_SCOPE.afterInitialRequest();
});
APP_SCOPE.getCurrentState(function(data) {
APP_SCOPE.currentState = data;
APP_SCOPE.afterInitialRequest();
});
if (window.external)
window.external.setMinSize(775, 200);
if (APP_SCOPE.external)
APP_SCOPE.external.setMinSize(775, 200);
APP_SCOPE.add_new_backup = function()
{
window.activateFunction("new-backup");
}
APP_SCOPE.scheduleHtmlTemplate = '' +
'<div id="%id%" class="status-window-row %oddorevenclass%">' +
' <div class="status-window-row-inner status-window-row-inner-left" >' +
' <div class="status-window-row-inner-content">%schedule%</div>' +
' </div>' +
' <div class="status-window-row-inner status-window-row-inner-middle">' +
' <div>' +
' <div class="ui-state-default ui-corner-all vertical-center status-window-name-bubble"><div><span>%name%</span><span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s" style="display: inline-block"></span></div></div>' +
' <div class="ui-state-default ui-corner-all vertical-center status-window-detail-area">' +
' <div>%metadata%</div>' +
' <div>%labels%</div>' +
' </div>' +
' </div>' +
' </div>' +
' <div class="status-window-row-inner status-window-row-inner-right">' +
' <div class="status-window-row-inner-content">' +
' <div>%error%</div>' +
' </div>' +
' </div>' +
'</div>';
});
(function(){
APP_SCOPE.afterInitialRequest = function() {
//Check that all required data is loaded, this prevents
if (this.backupSchedules != null && this.applicationSettings != null) {
if (this.backupSchedules != null && this.applicationSettings != null && this.currentState != null) {
$('#modal-cover').hide();
$('#progress-loader').hide();
this.buildBackupDisplay();
@@ -44,20 +72,63 @@ $(document).ready(function(){
var sc = APP_SCOPE.backupSchedules[i];
var id = 'backup-schedule-' + sc.ID;
var oddClass = (i % 2) == 1 ? 'odd' : 'even';
html += '<div id="'+ id + '" class="backup-schedule ' + oddClass + '">';
html += '<div class="backup-schedule-inner ui-corner-all ui-helper-clearfix ui-helper">';
html += '<div class="backup-schedule-name">' + sc.Name + '</div>';
if (sc.Tags != null && sc.Tags != '')
html += '<div class="backup-schedule-tags">' + sc.Tags + '</div>';
if (sc.Path != null && sc.Path != '')
html += '<div class="backup-schedule-path">' + sc.Path + '</div>';
html += '</div>';
html += '</div>';
var templateFilled = APP_SCOPE.scheduleHtmlTemplate.replace("%name%", sc.Name).replace("%id%", "id").replace("%oddorevenclass%", oddClass);
var labels = '';
if ((sc.Tags != null && sc.Tags != '') || (sc.Path != null && sc.Path != ''))
{
labels = 'Labels: ';
if (sc.Tags != null && sc.Tags != '')
labels += sc.Tags;
if (sc.Path != null && sc.Path != '')
labels += sc.Path;
}
//TODO: Figure out what the scheduler state is
var schedule = '';
//Is the backup running?
if (sc.ID == APP_SCOPE.currentState.ActiveScheduleId) {
schedule = '<div>Running</div><div class="link">Cancel</div>';
} else {
//Is the backup in queue?
var queueIndex = -1;
if (APP_SCOPE.currentState.SchedulerQueueIds != null)
for(var sci = 0; sci < APP_SCOPE.currentState.SchedulerQueueIds.length; sci++)
if (APP_SCOPE.currentState.SchedulerQueueIds[sci] == sc.ID)
{
queueIndex = sci;
break;
}
if (queueIndex >= 0) {
schedule = "No. " + (queueIndex + 1) + " in queue";
} else {
//Is the backup scheduled?
if (sc.NextScheduledTime != null)
{
var scdate = APP_SCOPE.toJsDate(sc.NextScheduledTime);
schedule = '<span title="' + scdate.toLocaleString() + '">' + jQuery.timeago(scdate) + '</span>';
}
}
}
//TODO: Make some logic to extract the last error message
var error = 'placeholder for error message';
//TODO: Extract some metadata
var metadata = 'placeholder for metadata';
templateFilled = templateFilled.replace("%labels%", labels).replace("%schedule%", schedule).replace("%error%", error).replace("%metadata%", metadata);
html += templateFilled;
}
container.innerHTML = html;
this.applyRoundedCornerClass();
container.innerHTML = html;
};
}());
+2 -2
View File
@@ -8,6 +8,7 @@
<link rel="stylesheet" href="stylesheets/customized.css" />
<script language="javascript" src="scripts/jquery-1.7.1.js" ></script>
<script language="javascript" src="scripts/jquery.timeago.js" ></script>
<script language="javascript" src="scripts/app-base.js" ></script>
<script language="javascript" src="scripts/app-functions.js" ></script>
@@ -16,14 +17,13 @@
<script language="javascript" src="scripts/customized.js" ></script>
</head>
<body>
<div id="modal-cover" class="modal-cover"></div>
<div id="progress-loader" class="loader ui-corner-all">Loading ...</div>
<div id="status-window-toolbar">
<div id="status-window-toolbar-inner" class="ui-state-default ui-helper-clearfix ui-helper ui-widget-header">
<div id="status-window-main-logo" title="Click to access basic functions" class="ui-state-default ui-helper-clearfix ui-helper ui-widget-header ui-corner-all">
<div id="appname" class="appname"></div>
<div id="appname" class="appname"></div><span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s"></span>
</div>
<div id="status-window-news" title="Click here to open the news page">A new version of Duplicati is available</div>
@@ -39,77 +39,14 @@ body
background-color: white;
}
.odd { background-color: #efefef; }
.drop-arrow
.even { background-color: #efefef; }
.odd { background-color: #ffffff; }
.link
{
width: 7px;
height: 7px;
background-image: url('../gfx/drop-arrow.gif');
background-repeat: no-repeat;
color: darkblue;
text-decoration: underline;
cursor: pointer;
}
.round-corner-box
{
border-collapse: collapse;
padding: 0;
margin: 0;
border-spacing; 0px;
}
.round-corner-box .top,
.round-corner-box .bottom
{ height: 5px; }
.round-corner-box .top .left,
.round-corner-box .top .right,
.round-corner-box .center .left,
.round-corner-box .center .right,
.round-corner-box .bottom .left,
.round-corner-box .bottom .right
{
width: 5px;
height: 5px;
}
.round-corner-box .top .left,
.round-corner-box .top .right,
.round-corner-box .bottom .left,
.round-corner-box .bottom .right
{
background-repeat: no-repeat;
}
.round-corner-box .top .left,
.round-corner-box .top .right,
.round-corner-box .bottom .left,
.round-corner-box .bottom .right
{
background-image: url('../gfx/round-box3.gif');
}
.round-corner-box .center .left,
.round-corner-box .center .right,
.round-corner-box .top .middle,
.round-corner-box .bottom .middle
{
background-image: url('../gfx/round-dot.gif');
}
.round-corner-box .center .left,
.round-corner-box .center .right
{ background-repeat: repeat-y; }
.round-corner-box .top .middle,
.round-corner-box .bottom .middle
{ background-repeat: repeat-x; }
.round-corner-box .top .left { background-position: 0px 0px; }
.round-corner-box .top .right { background-position: -5px 0px; }
.round-corner-box .bottom .left { background-position: 0px -5px; }
.round-corner-box .bottom .right { background-position: -5px -5px; }
.round-corner-box .top .middle { background-position: 0px 0px; }
.round-corner-box .bottom .middle { background-position: 0px 4px; }
.round-corner-box .center .left { background-position: 0px 0px; }
.round-corner-box .center .right { background-position: 4px 0px; }
.vertical-center { margin: 0px auto; }
@@ -8,7 +8,7 @@ body
{
min-width: 675px;
min-height: 200px;
display: none;
display: block;
}
.status-window-toolbar-item
@@ -131,6 +131,54 @@ body
border: 1px solid red;
}
.backup-schedule-name
.status-window-name-bubble
{
width: 240px;
}
.status-window-row
{
height: 120px;
padding-top: 10px;
padding-bottom: 10px;
}
.status-window-row-inner
{
width: 33%;
height: 100%;
float: left;
vertical-align: middle;
}
.status-window-row-inner-left
{
text-align: right;
}
.status-window-row-inner-middle
{
text-align: center;
}
.status-window-row-inner-right
{
text-align: left;
}
.status-window-row-inner-content
{
padding-right: 20px;
padding-left: 20px;
padding-top: 30px;
}
.status-window-detail-area
{
margin-top: -1px;
padding-top: 11px;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
min-width: 220px;
}