Compare commits
10 Commits
1ea1d7d75f
...
a3941843b1
Author | SHA1 | Date | |
---|---|---|---|
|
a3941843b1 | ||
|
7ba8d76843 | ||
|
64e90eaeb5 | ||
|
bf20564858 | ||
|
0a083ba8cc | ||
|
9bd00cdab7 | ||
|
60e76118e3 | ||
|
98b5208adb | ||
|
0224a1cd0a | ||
|
563edb4f5d |
21
Makefile
21
Makefile
@ -1,14 +1,27 @@
|
|||||||
build :
|
VERSION =1.5
|
||||||
|
BUILD_NUMBER_FILE = build-number.txt
|
||||||
|
BUILD_NUMBER = $$(cat $(BUILD_NUMBER_FILE))
|
||||||
|
|
||||||
|
build : increment-build-number
|
||||||
mkdir -p build/css
|
mkdir -p build/css
|
||||||
|
mkdir -p build/js
|
||||||
cp src/www/*.* build
|
cp src/www/*.* build
|
||||||
cp -r src/www/js build
|
|
||||||
cp -r resources/* build/.
|
cp -r resources/* build/.
|
||||||
|
cp src/www/js/personal-display.js build/js/personal-display-$(VERSION).$(BUILD_NUMBER).js
|
||||||
|
sed -i "s/%VERSION%/$(VERSION).$(BUILD_NUMBER)/g" build/index.html
|
||||||
sass src/www/css/personal-display.scss build/css/personal-display.css
|
sass src/www/css/personal-display.scss build/css/personal-display.css
|
||||||
tar czf personal-display.tar.gz build
|
tar czf personal-display-$(VERSION).$(BUILD_NUMBER).tar.gz build
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -r build
|
-rm -r build
|
||||||
|
|
||||||
local-deploy: build
|
local-deploy: build
|
||||||
cp -r build ~/temp/server
|
cp -r build ~/temp/server
|
||||||
ssh jdb-server 'rm -r ~/public_html/personal-display; mv temp/build ~/public_html/personal-display'
|
ssh jdb-server 'rm -r ~/public_html/personal-display; mv temp/build ~/public_html/personal-display'
|
||||||
|
|
||||||
|
increment-build-number:
|
||||||
|
if ! test -f $(BUILD_NUMBER_FILE); then echo 0 > $(BUILD_NUMBER_FILE); fi
|
||||||
|
echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE)
|
||||||
|
|
||||||
|
test-build-number:
|
||||||
|
touch $(BUILD_NUMBER).text.txt
|
||||||
|
1
build-number.txt
Normal file
1
build-number.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
19
|
@ -142,7 +142,8 @@ body > section {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 66%;
|
font-size: 66%;
|
||||||
margin: 0 0.5rem;
|
margin: 0 0.5rem;
|
||||||
max-width: 33%;
|
max-width: 66%;
|
||||||
|
overflow: hidden;
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
white-space: nowrap; }
|
white-space: nowrap; }
|
||||||
|
|
||||||
@ -250,3 +251,23 @@ body > section {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 } }
|
padding: 0 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main-buttons {
|
||||||
|
border-top: solid 2px $accent1;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
border: $accent2 solid thin;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.1rem 0.3rem; } } }
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
<title>What I am Doing</title>
|
<title>What I am Doing</title>
|
||||||
<link rel="stylesheet" href="css/personal-display.css" type="text/css">
|
<link rel="stylesheet" href="css/personal-display.css" type="text/css">
|
||||||
<link href='//fonts.googleapis.com/css?family=Play|Advent+Pro' rel='stylesheet' type='text/css'>
|
<link href='//fonts.googleapis.com/css?family=Play|Advent+Pro' rel='stylesheet' type='text/css'>
|
||||||
@ -17,9 +18,10 @@
|
|||||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone.js" defer></script>
|
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone.js" defer></script>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script src="js/personal-display.js" type="text/javascript" defer></script>
|
<script src="js/personal-display-%VERSION%.js" type="text/javascript" defer></script>
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
|
<meta name=version content="1.5">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<section id=current-task>
|
<section id=current-task>
|
||||||
@ -30,12 +32,22 @@
|
|||||||
<section id=priorities>
|
<section id=priorities>
|
||||||
<h3>Next Actions (unsorted)</h3>
|
<h3>Next Actions (unsorted)</h3>
|
||||||
</section>
|
</section>
|
||||||
|
<section id=main-buttons>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#" class=pause-continue>Pause Monitoring</a></li>
|
||||||
|
<li><a href="#" class=refresh>Refresh Now</a></li>
|
||||||
|
<li><a href="#" class=show-config>Config</a></li>
|
||||||
|
<li><a href="#" class=toggle-fullscreen>Go Fullscreen</a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
<section id=config-dialog>
|
<section id=config-dialog>
|
||||||
<form>
|
<form>
|
||||||
<h3>Configuration</h3>
|
<h3>Configuration</h3>
|
||||||
<span class=validate-tips></span>
|
<span class=validate-tips></span>
|
||||||
<section class=timestamper-config>
|
<section class=timestamper-config>
|
||||||
<span class=config-section-header>TimeStamper</span>
|
<span class=config-section-header>TimeStamper</span>
|
||||||
|
<div class=enabled><label>Enabled?</label>
|
||||||
|
<input type=checkbox class=enabled></div>
|
||||||
<div><label>Server Name: </label>
|
<div><label>Server Name: </label>
|
||||||
<input type=text class=host></div>
|
<input type=text class=host></div>
|
||||||
<div><label>Username: </label>
|
<div><label>Username: </label>
|
||||||
@ -49,6 +61,8 @@
|
|||||||
</section>
|
</section>
|
||||||
<section class=gtd-config>
|
<section class=gtd-config>
|
||||||
<span class=config-section-header>Getting Things Done</span>
|
<span class=config-section-header>Getting Things Done</span>
|
||||||
|
<div class=enabled><label>Enabled?</label>
|
||||||
|
<input type=checkbox class=enabled></div>
|
||||||
<div><label>Server Name: </label>
|
<div><label>Server Name: </label>
|
||||||
<input type=text class=host></div>
|
<input type=text class=host></div>
|
||||||
<div><label>Username: </label>
|
<div><label>Username: </label>
|
||||||
@ -63,7 +77,7 @@
|
|||||||
<div class=button-panel>
|
<div class=button-panel>
|
||||||
<div class=global-config>
|
<div class=global-config>
|
||||||
<label>Refresh (sec): </label>
|
<label>Refresh (sec): </label>
|
||||||
<input type=text class=refresh></div>
|
<input type=text class=refresh-period></div>
|
||||||
<div class=save-button><a href="#">Save and Close</a></div>
|
<div class=save-button><a href="#">Save and Close</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class=wait-overlay><img src="img/loading-spinner.gif"><br><span></span></div>
|
<div class=wait-overlay><img src="img/loading-spinner.gif"><br><span></span></div>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
var root = this;
|
var root = this;
|
||||||
|
|
||||||
var PD = root.PersonalDisplay = {};
|
var PD = root.PersonalDisplay = {};
|
||||||
|
PD.version = "1.5"
|
||||||
|
|
||||||
PD.hasHTML5LocalStorage = function() {
|
PD.hasHTML5LocalStorage = function() {
|
||||||
try {
|
try {
|
||||||
@ -109,12 +110,13 @@
|
|||||||
"change .gtd-config .category" : "addCategory",
|
"change .gtd-config .category" : "addCategory",
|
||||||
"click .remove-button" : "removeCategory",
|
"click .remove-button" : "removeCategory",
|
||||||
|
|
||||||
"click .save-button" : "saveAndClose" },
|
"click .save-button" : "saveAndClose",
|
||||||
|
"change input.enabled" : "enableDisable"},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
_.bindAll(this, "show", "hide", "tsLogin", "gtdLogin",
|
_.bindAll(this, "addCategory", "enableDisable", "gtdLogin", "hide",
|
||||||
"loadTsData", "loadGtdData", "addCategory", "makeCategoryItem",
|
"loadGtdData", "loadTsData", "makeCategoryItem", "removeCategory",
|
||||||
"removeCategory", "saveAndClose"); },
|
"saveAndClose", "show", "tsLogin"); },
|
||||||
|
|
||||||
show: function() {
|
show: function() {
|
||||||
var $tsSection = this.$el.find(".timestamper-config");
|
var $tsSection = this.$el.find(".timestamper-config");
|
||||||
@ -125,11 +127,13 @@
|
|||||||
$tsSection.find(".username").val(PD.tsCfg.username);
|
$tsSection.find(".username").val(PD.tsCfg.username);
|
||||||
$tsSection.find(".password").val(PD.tsCfg.password);
|
$tsSection.find(".password").val(PD.tsCfg.password);
|
||||||
$tsSection.find(".host").val(PD.tsCfg.host);
|
$tsSection.find(".host").val(PD.tsCfg.host);
|
||||||
|
$tsSection.find("input.enabled")[0].checked = PD.tsCfg.enabled;
|
||||||
|
|
||||||
if (PD.tsAuth) {
|
if (PD.tsAuth) {
|
||||||
this.loadTsData(PD.tsCfg.host, PD.tsCfg.username); }
|
this.loadTsData(PD.tsCfg.host, PD.tsCfg.username); }
|
||||||
|
|
||||||
this.$el.find('.timeline').val(PD.tsCfg.timelineId); }
|
this.$el.find('.timeline').val(PD.tsCfg.timelineId);
|
||||||
|
this.enableDisable({target: $tsSection.find("input.enabled")[0]}); }
|
||||||
|
|
||||||
// Or suggest a default server.
|
// Or suggest a default server.
|
||||||
else { $tsSection.find(".host").val("timestamper.jdb-labs.com"); }
|
else { $tsSection.find(".host").val("timestamper.jdb-labs.com"); }
|
||||||
@ -139,14 +143,17 @@
|
|||||||
$gtdSection.find(".username").val(PD.gtdCfg.username);
|
$gtdSection.find(".username").val(PD.gtdCfg.username);
|
||||||
$gtdSection.find(".password").val(PD.gtdCfg.password);
|
$gtdSection.find(".password").val(PD.gtdCfg.password);
|
||||||
$gtdSection.find(".host").val(PD.gtdCfg.host);
|
$gtdSection.find(".host").val(PD.gtdCfg.host);
|
||||||
|
$gtdSection.find("input.enabled")[0].checked = PD.gtdCfg.enabled;
|
||||||
|
|
||||||
if (PD.gtdAuth) { this.loadGtdData(PD.gtdCfg.host); }
|
if (PD.gtdAuth) { this.loadGtdData(PD.gtdCfg.host); }
|
||||||
|
|
||||||
// Create the items for the selected categories
|
// Create the items for the selected categories
|
||||||
$(".category-name").parent().remove();
|
$(".category-name").parent().remove();
|
||||||
_.forEach(PD.gtdCfg.categories, this.makeCategoryItem); }
|
_.forEach(PD.gtdCfg.categories, this.makeCategoryItem);
|
||||||
|
|
||||||
|
this.enableDisable({target: $gtdSection.find("input.enabled")[0]}); }
|
||||||
|
|
||||||
this.$el.find('.refresh').val(
|
this.$el.find('.refresh-period').val(
|
||||||
PD.refreshPeriod ? PD.refreshPeriod / 1000 : 15);
|
PD.refreshPeriod ? PD.refreshPeriod / 1000 : 15);
|
||||||
|
|
||||||
this.$el.fadeIn(); },
|
this.$el.fadeIn(); },
|
||||||
@ -157,6 +164,7 @@
|
|||||||
var username = this.$el.find(".timestamper-config .username").val();
|
var username = this.$el.find(".timestamper-config .username").val();
|
||||||
var password = this.$el.find(".timestamper-config .password").val();
|
var password = this.$el.find(".timestamper-config .password").val();
|
||||||
var host = this.$el.find(".timestamper-config .host").val();
|
var host = this.$el.find(".timestamper-config .host").val();
|
||||||
|
var thisView = this;
|
||||||
|
|
||||||
if (!PD.tsCfg) { PD.tsCfg = {}; }
|
if (!PD.tsCfg) { PD.tsCfg = {}; }
|
||||||
|
|
||||||
@ -170,7 +178,6 @@
|
|||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
processData: false,
|
processData: false,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
async: false,
|
|
||||||
|
|
||||||
data: JSON.stringify(
|
data: JSON.stringify(
|
||||||
{"username": username, "password": password}),
|
{"username": username, "password": password}),
|
||||||
@ -182,7 +189,10 @@
|
|||||||
else { $(".validate-tips").text("There was an error " +
|
else { $(".validate-tips").text("There was an error " +
|
||||||
"trying to log into the TimeStamper service: " +
|
"trying to log into the TimeStamper service: " +
|
||||||
error); }
|
error); }
|
||||||
PD.tsAuth = false; },
|
PD.tsAuth = false;
|
||||||
|
|
||||||
|
// Hide the wait overlay.
|
||||||
|
thisView.$el.find(".wait-overlay").fadeOut(); },
|
||||||
|
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
PD.tsAuth = true;
|
PD.tsAuth = true;
|
||||||
@ -191,11 +201,10 @@
|
|||||||
|
|
||||||
// Load the user's timelines.
|
// Load the user's timelines.
|
||||||
PD.configDialog.loadTsData(host, username);
|
PD.configDialog.loadTsData(host, username);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Success or failure we hide the wait overlay.
|
// Hide the wait overlay.
|
||||||
this.$el.find(".wait-overlay").fadeOut();
|
thisView.$el.find(".wait-overlay").fadeOut(); }
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -203,6 +212,7 @@
|
|||||||
var username = this.$el.find(".gtd-config .username").val();
|
var username = this.$el.find(".gtd-config .username").val();
|
||||||
var password = this.$el.find(".gtd-config .password").val();
|
var password = this.$el.find(".gtd-config .password").val();
|
||||||
var host = this.$el.find(".gtd-config .host").val();
|
var host = this.$el.find(".gtd-config .host").val();
|
||||||
|
var thisView = this;
|
||||||
|
|
||||||
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
|
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
|
||||||
|
|
||||||
@ -216,7 +226,6 @@
|
|||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
processData: false,
|
processData: false,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
async: false,
|
|
||||||
|
|
||||||
data: JSON.stringify(
|
data: JSON.stringify(
|
||||||
{"username": username, "password": password}),
|
{"username": username, "password": password}),
|
||||||
@ -228,61 +237,71 @@
|
|||||||
else { $(".validate-tips").text("There was an error " +
|
else { $(".validate-tips").text("There was an error " +
|
||||||
"trying to log into the Getting Things Done service: " +
|
"trying to log into the Getting Things Done service: " +
|
||||||
error); }
|
error); }
|
||||||
PD.gtdAuth = false; },
|
PD.gtdAuth = false;
|
||||||
|
thisView.$el.find(".wait-overlay").fadeOut(); },
|
||||||
|
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
PD.gtdAuth = true;
|
PD.gtdAuth = true;
|
||||||
|
|
||||||
$(".validate-tips").text("");
|
$(".validate-tips").text("");
|
||||||
|
|
||||||
PD.configDialog.loadGtdData(host); }
|
PD.configDialog.loadGtdData(host);
|
||||||
|
thisView.$el.find(".wait-overlay").fadeOut(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$el.find(".wait-overlay").fadeOut();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loadTsData: function(host, username) {
|
loadTsData: function(host, username) {
|
||||||
|
var thisView = this;
|
||||||
// (Re)load the user's timelines.
|
// (Re)load the user's timelines.
|
||||||
PD.tsCfg.timelines = JSON.parse($.ajax({
|
$.ajax({
|
||||||
url: 'https://' + host + '/ts_api/timelines/' + username,
|
url: 'https://' + host + '/ts_api/timelines/' + username,
|
||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
async: false}).responseText);
|
success: function(data, textStatus, jqXHR) {
|
||||||
|
PD.tsCfg.timelines = data;
|
||||||
|
|
||||||
// Populate the available timelines list.
|
// Populate the available timelines list.
|
||||||
var $timelineSelectEl = this.$el.find(".timestamper-config .timeline");
|
var $timelineSelectEl = $(".timestamper-config .timeline");
|
||||||
$timelineSelectEl.empty();
|
|
||||||
_.forEach(PD.tsCfg.timelines, function(timeline) {
|
$timelineSelectEl.empty();
|
||||||
var $optionEl = $(document.createElement("option"));
|
_.forEach(PD.tsCfg.timelines, function(timeline) {
|
||||||
$optionEl.attr("value", timeline.id);
|
var $optionEl = $(document.createElement("option"));
|
||||||
$optionEl.text(timeline.description);
|
$optionEl.attr("value", timeline.id);
|
||||||
$timelineSelectEl.append($optionEl); }); },
|
$optionEl.text(timeline.description);
|
||||||
|
$timelineSelectEl.append($optionEl); });
|
||||||
|
}}); },
|
||||||
|
|
||||||
loadGtdData: function(host) {
|
loadGtdData: function(host) {
|
||||||
|
|
||||||
|
|
||||||
// Load the user's contexts
|
// Load the user's contexts
|
||||||
PD.gtdCfg.contexts = JSON.parse($.ajax({
|
var contextLoaded = $.ajax({
|
||||||
url: 'http://' + host + '/gtd/contexts',
|
url: 'http://' + host + '/gtd/contexts',
|
||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
async: false }).responseText);
|
success: function(data, textStatus, jqXHR) {
|
||||||
|
PD.gtdCfg.contexts = data;} });
|
||||||
|
|
||||||
// Load the user's projects
|
// Load the user's projects
|
||||||
PD.gtdCfg.projects = JSON.parse($.ajax({
|
var projectsLoaded = $.ajax({
|
||||||
url: 'http://' + host + '/gtd/projects',
|
url: 'http://' + host + '/gtd/projects',
|
||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
async: false }).responseText);
|
success: function(data, statuxText, jqXHR) {
|
||||||
|
PD.gtdCfg.projects = data;} });
|
||||||
|
|
||||||
// Populate the available contexts and projects drop-down.
|
$.when(contextLoaded, projectsLoaded).then(function() {
|
||||||
var $categorySelectEl = $(".gtd-config .category")
|
// Populate the available contexts and projects drop-down.
|
||||||
$categorySelectEl.empty();
|
var $categorySelectEl = $(".gtd-config .category")
|
||||||
$categorySelectEl.append(
|
$categorySelectEl.empty();
|
||||||
"<option class=default-option value='none'>" +
|
$categorySelectEl.append(
|
||||||
"Add a category...</option>");
|
"<option class=default-option value='none'>" +
|
||||||
_.forEach(PD.gtdCfg.contexts.concat(PD.gtdCfg.projects),
|
"Add a category...</option>");
|
||||||
function(category) {
|
_.forEach(PD.gtdCfg.contexts.concat(PD.gtdCfg.projects),
|
||||||
var $optionEl = $(document.createElement("option"));
|
function(category) {
|
||||||
$optionEl.attr("value", category.id);
|
var $optionEl = $(document.createElement("option"));
|
||||||
$optionEl.text(category.id);
|
$optionEl.attr("value", category.id);
|
||||||
$categorySelectEl.append($optionEl); });
|
$optionEl.text(category.id);
|
||||||
$categorySelectEl[0].selectedIndex = 0; },
|
$categorySelectEl.append($optionEl); });
|
||||||
|
$categorySelectEl[0].selectedIndex = 0; }); },
|
||||||
|
|
||||||
makeCategoryItem: function(catName) {
|
makeCategoryItem: function(catName) {
|
||||||
var $liEl = $(
|
var $liEl = $(
|
||||||
@ -301,6 +320,18 @@
|
|||||||
removeCategory: function(source) {
|
removeCategory: function(source) {
|
||||||
$(source.target).parent().remove(); },
|
$(source.target).parent().remove(); },
|
||||||
|
|
||||||
|
enableDisable: function (e) {
|
||||||
|
var cbEl = e.target;
|
||||||
|
var $cbEl = $(cbEl);
|
||||||
|
var $section = $cbEl.closest('section');
|
||||||
|
|
||||||
|
if (cbEl.checked) {
|
||||||
|
$section.find('div, ul').show(); }
|
||||||
|
|
||||||
|
else {
|
||||||
|
$section.find('div, ul').hide();
|
||||||
|
$section.find('div.enabled').show(); } },
|
||||||
|
|
||||||
saveAndClose: function() {
|
saveAndClose: function() {
|
||||||
if (!PD.tsCfg) { PD.tsCfg = {}; }
|
if (!PD.tsCfg) { PD.tsCfg = {}; }
|
||||||
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
|
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
|
||||||
@ -311,18 +342,20 @@
|
|||||||
PD.tsCfg.username = $tsEl.find(".username").val();
|
PD.tsCfg.username = $tsEl.find(".username").val();
|
||||||
PD.tsCfg.password = $tsEl.find(".password").val();
|
PD.tsCfg.password = $tsEl.find(".password").val();
|
||||||
PD.tsCfg.timelineId = $tsEl.find(".timeline").val();
|
PD.tsCfg.timelineId = $tsEl.find(".timeline").val();
|
||||||
|
PD.tsCfg.enabled = $tsEl.find("input.enabled")[0].checked;
|
||||||
|
|
||||||
// Save Getting Things Done configuration.
|
// Save Getting Things Done configuration.
|
||||||
var $gtdEl = this.$el.find(".gtd-config");
|
var $gtdEl = this.$el.find(".gtd-config");
|
||||||
PD.gtdCfg.host = $gtdEl.find(".host").val();
|
PD.gtdCfg.host = $gtdEl.find(".host").val();
|
||||||
PD.gtdCfg.username = $gtdEl.find(".username").val();
|
PD.gtdCfg.username = $gtdEl.find(".username").val();
|
||||||
PD.gtdCfg.password = $gtdEl.find(".password").val();
|
PD.gtdCfg.password = $gtdEl.find(".password").val();
|
||||||
|
PD.gtdCfg.enabled = $gtdEl.find("input.enabled")[0].checked;
|
||||||
PD.gtdCfg.categories = _.map(
|
PD.gtdCfg.categories = _.map(
|
||||||
this.$el.find(".category-name"),
|
this.$el.find(".category-name"),
|
||||||
function(span) { return $(span).text(); });
|
function(span) { return $(span).text(); });
|
||||||
|
|
||||||
// Save global data
|
// Save global data
|
||||||
PD.refreshPeriod = parseInt(this.$el.find(".refresh").val()) * 1000;
|
PD.refreshPeriod = parseInt(this.$el.find(".refresh-period").val()) * 1000;
|
||||||
|
|
||||||
if (PD.hasHTML5LocalStorage()) {
|
if (PD.hasHTML5LocalStorage()) {
|
||||||
localStorage.setItem("tsCfg", JSON.stringify(PD.tsCfg));
|
localStorage.setItem("tsCfg", JSON.stringify(PD.tsCfg));
|
||||||
@ -330,16 +363,22 @@
|
|||||||
localStorage.setItem("refreshPeriod",
|
localStorage.setItem("refreshPeriod",
|
||||||
JSON.stringify(PD.refreshPeriod)); }
|
JSON.stringify(PD.refreshPeriod)); }
|
||||||
|
|
||||||
this.hide();
|
this.hide(400, PD.main.refresh);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PD.Main = Backbone.View.extend({
|
PD.Main = Backbone.View.extend({
|
||||||
el: $("body"),
|
el: $("body"),
|
||||||
|
|
||||||
|
events: {
|
||||||
|
"click a.refresh" : "refresh",
|
||||||
|
"click a.pause-continue" : "toggleSync",
|
||||||
|
"click a.show-config" : "showConfig",
|
||||||
|
"click a.toggle-fullscreen" : "toggleFullscreen" },
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
|
|
||||||
_.bindAll(this, "refresh");
|
_.bindAll(this, "refresh", "toggleSync");
|
||||||
|
|
||||||
// Create our config dialog view.
|
// Create our config dialog view.
|
||||||
PD.configDialog = new PD.ConfigDialog();
|
PD.configDialog = new PD.ConfigDialog();
|
||||||
@ -366,10 +405,11 @@
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
|
|
||||||
// Schedule future refreshes.
|
// Schedule future refreshes.
|
||||||
setInterval(this.refresh, PD.refreshPeriod ? PD.refreshPeriod : 15000);
|
PD.refreshIntervalId = setInterval(this.refresh, PD.refreshPeriod ? PD.refreshPeriod : 15000);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function(evt) {
|
||||||
// If the dialog is still open we skip this sync to give the user
|
// If the dialog is still open we skip this sync to give the user
|
||||||
// a chance to finish configuration.
|
// a chance to finish configuration.
|
||||||
if ($("#config-dialog").is(":visible")) { return; }
|
if ($("#config-dialog").is(":visible")) { return; }
|
||||||
@ -380,13 +420,12 @@
|
|||||||
|
|
||||||
// Check that we are authenticated to the services we need. Try to
|
// Check that we are authenticated to the services we need. Try to
|
||||||
// authenticate if we are not.
|
// authenticate if we are not.
|
||||||
if (!PD.tsAuth) {
|
if (PD.tsCfg.enabled && !PD.tsAuth) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "https://" + PD.tsCfg.host + "/ts_api/login",
|
url: "https://" + PD.tsCfg.host + "/ts_api/login",
|
||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
processData: false,
|
processData: false,
|
||||||
type: "POST",
|
type: "POST",
|
||||||
async: false,
|
|
||||||
|
|
||||||
data: JSON.stringify(
|
data: JSON.stringify(
|
||||||
{ "username": PD.tsCfg.username,
|
{ "username": PD.tsCfg.username,
|
||||||
@ -402,13 +441,12 @@
|
|||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
PD.tsAuth = true; }}); }
|
PD.tsAuth = true; }}); }
|
||||||
|
|
||||||
if (!PD.gtdAuth) {
|
if (PD.gtdCfg.enabled && !PD.gtdAuth) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "http://" + PD.gtdCfg.host + "/gtd/login",
|
url: "http://" + PD.gtdCfg.host + "/gtd/login",
|
||||||
xhrFields: { withCredentials: true },
|
xhrFields: { withCredentials: true },
|
||||||
processData: false,
|
processData: false,
|
||||||
type: "POST",
|
type: "POST",
|
||||||
async: false,
|
|
||||||
|
|
||||||
data: JSON.stringify(
|
data: JSON.stringify(
|
||||||
{ "username": PD.gtdCfg.username,
|
{ "username": PD.gtdCfg.username,
|
||||||
@ -427,71 +465,123 @@
|
|||||||
|
|
||||||
// Check that we have successfully authenticated to both services.
|
// Check that we have successfully authenticated to both services.
|
||||||
// If we are not, we will skip this refresh.
|
// If we are not, we will skip this refresh.
|
||||||
if (!(PD.tsAuth && PD.gtdAuth)) { return; }
|
if ((PD.tsCfg.enabled && !PD.tsAuth) ||
|
||||||
|
(PD.gtdCfg.enabled && !PD.gtdAuth)) { return; }
|
||||||
|
|
||||||
// Get the latest timestamp from the TimeStamper service.
|
// Get the latest timestamp from the TimeStamper service.
|
||||||
$.ajax({
|
if (PD.tsCfg.enabled) {
|
||||||
url: "https://" + PD.tsCfg.host + "/ts_api/entries/" +
|
$("section#current-task").show();
|
||||||
PD.tsCfg.username + "/" + PD.tsCfg.timelineId,
|
$.ajax({
|
||||||
xhrFields: { withCredentials: true },
|
url: "https://" + PD.tsCfg.host + "/ts_api/entries/" +
|
||||||
data: {"order": "asc" },
|
PD.tsCfg.username + "/" + PD.tsCfg.timelineId,
|
||||||
dataType: 'json',
|
xhrFields: { withCredentials: true },
|
||||||
type: 'GET',
|
data: {"order": "asc" },
|
||||||
async: true,
|
dataType: 'json',
|
||||||
|
type: 'GET',
|
||||||
|
async: true,
|
||||||
|
|
||||||
error: function(jqXHR, textStatus, errorText) {
|
error: function(jqXHR, textStatus, errorText) {
|
||||||
if (jqXHR.status == 401) { PD.tsAuth = false; }
|
if (jqXHR.status == 401) { PD.tsAuth = false; }
|
||||||
else {
|
else {
|
||||||
alert("Unable to retrieve current timestamp: " + errorText);
|
alert("Unable to retrieve current timestamp: " +
|
||||||
PD.configDialog.show(); }
|
errorText);
|
||||||
},
|
PD.configDialog.show(); } },
|
||||||
|
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
PD.currentActivityModel.set(data[0]); }
|
PD.currentActivityModel.set(data[0]); } }); }
|
||||||
});
|
|
||||||
|
// If the TimeStamper section is not enabled, hide the UI for it
|
||||||
|
else $("section#current-task").hide();
|
||||||
|
|
||||||
// Get the list of GTD entries for each of our categories.
|
// Get the list of GTD entries for each of our categories.
|
||||||
var categories = _.reduce(
|
if (PD.gtdCfg.enabled) {
|
||||||
PD.gtdCfg.categories,
|
var categories = _.reduce(
|
||||||
function(acc, cat) { return acc ? acc + "," + cat : cat; }, "");
|
PD.gtdCfg.categories,
|
||||||
|
function(acc, cat) { return acc ? acc + "," + cat : cat; }, "");
|
||||||
|
|
||||||
$.ajax({
|
$("section#priorities").show();
|
||||||
url: "http://" + PD.gtdCfg.host + "/gtd/next-actions/" +
|
$.ajax({
|
||||||
categories,
|
url: "http://" + PD.gtdCfg.host + "/gtd/next-actions/" +
|
||||||
xhrFields: { withCredentials: true },
|
categories,
|
||||||
dataType: 'json',
|
xhrFields: { withCredentials: true },
|
||||||
type: 'GET',
|
dataType: 'json',
|
||||||
async: true,
|
type: 'GET',
|
||||||
|
async: true,
|
||||||
|
|
||||||
error: function(jqXHR, textStatus, errorText) {
|
error: function(jqXHR, textStatus, errorText) {
|
||||||
if (jqXHR.status == 401) { PD.gtdAtuh = false; }
|
if (jqXHR.status == 401) { PD.gtdAtuh = false; }
|
||||||
else if (jqXHR.status == 500) { return; }
|
else if (jqXHR.status == 500) { return; }
|
||||||
else {
|
else {
|
||||||
alert("Unable to retrieve next actions: " + errorText);
|
alert("Unable to retrieve next actions: " +
|
||||||
PD.configDialog.show(); }
|
errorText);
|
||||||
},
|
PD.configDialog.show(); } },
|
||||||
|
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
var collection = PD.gtdNextActionCollection;
|
var collection = PD.gtdNextActionCollection;
|
||||||
|
|
||||||
// Add all the retrieved items to the collection.
|
// Add all the retrieved items to the collection.
|
||||||
_.forEach(data, function(actionAttr) {
|
_.forEach(data, function(actionAttr) {
|
||||||
|
|
||||||
// Try to find this entry in out collection.
|
// Try to find this entry in out collection.
|
||||||
var model = collection.get(actionAttr.id);
|
var model = collection.get(actionAttr.id);
|
||||||
// Update it if found
|
// Update it if found
|
||||||
if (model) { model.set(actionAttr); }
|
if (model) { model.set(actionAttr); }
|
||||||
// Insert a new model if not found.
|
// Insert a new model if not found.
|
||||||
else { collection.add(
|
else { collection.add(
|
||||||
new PD.GTDEntryModel(actionAttr)); }});
|
new PD.GTDEntryModel(actionAttr)); }});
|
||||||
|
|
||||||
// Look through our collection for entries that are no
|
// Look through our collection for entries that are no
|
||||||
// longer in our retrieved data and remove them.
|
// longer in our retrieved data and remove them.
|
||||||
collection.forEach(function(model) {
|
collection.forEach(function(model) {
|
||||||
if (!_.any(data, model.equals)) {
|
if (!_.any(data, model.equals)) {
|
||||||
collection.remove(model); }});
|
collection.remove(model); }}); } }); }
|
||||||
}
|
|
||||||
});
|
// If the GTD section is not enabled, hid the UI.
|
||||||
|
else $("section#priorities").hide();
|
||||||
|
|
||||||
|
if (evt) evt.preventDefault();
|
||||||
|
},
|
||||||
|
|
||||||
|
showConfig: function() { PD.configDialog.show(); },
|
||||||
|
|
||||||
|
toggleFullscreen: function(evt) {
|
||||||
|
var $button = $(evt.target);
|
||||||
|
if ($button.text() == "Go Fullscreen") {
|
||||||
|
|
||||||
|
if (document.documentElement.requestFullscreen) {
|
||||||
|
document.documentElement.requestFullscreen(); }
|
||||||
|
else if (document.documentElement.webkitRequestFullscreen) {
|
||||||
|
document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
|
||||||
|
else if (document.documentElement.mozRequestFullScreen) {
|
||||||
|
document.documentElement.mozRequestFullScreen(); }
|
||||||
|
else { alert ("Not supported by this browser."); }
|
||||||
|
|
||||||
|
$button.text("Leave Fullscreen"); }
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen(); }
|
||||||
|
else if (document.webkitExitFullscreen) {
|
||||||
|
document.webkitExitFullscreen(); }
|
||||||
|
else if (document.mozCancelFullscreen) {
|
||||||
|
document.documentElement.mozCancelFullscreen(); }
|
||||||
|
else { alert ("Not supported by this browser."); }
|
||||||
|
|
||||||
|
$button.text("Go Fullscreen"); } },
|
||||||
|
|
||||||
|
toggleSync: function(evt) {
|
||||||
|
if (PD.refreshIntervalId == null) {
|
||||||
|
PD.refreshIntervalId = setInterval(this.refresh,
|
||||||
|
PD.refreshPeriod ? PD.refreshPeriod : 15000);
|
||||||
|
$('.pause-continue').text('Pause Monitoring'); }
|
||||||
|
else {
|
||||||
|
clearInterval(PD.refreshIntervalId);
|
||||||
|
PD.refreshIntervalId = null;
|
||||||
|
$('.pause-continue').text('Resume Monitoring'); }
|
||||||
|
|
||||||
|
|
||||||
|
if (evt) evt.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user