Compare commits

..

No commits in common. "a3941843b182ee683294bafa23e7df9e07a97ea1" and "1ea1d7d75f53f7b8c8226a65db322fd1e1d1bc04" have entirely different histories.

5 changed files with 113 additions and 252 deletions

View File

@ -1,27 +1,14 @@
VERSION =1.5
BUILD_NUMBER_FILE = build-number.txt
BUILD_NUMBER = $$(cat $(BUILD_NUMBER_FILE))
build : increment-build-number
build :
mkdir -p build/css
mkdir -p build/js
cp src/www/*.* build
cp -r src/www/js 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
tar czf personal-display-$(VERSION).$(BUILD_NUMBER).tar.gz build
tar czf personal-display.tar.gz build
clean :
-rm -r build
rm -r build
local-deploy: build
cp -r build ~/temp/server
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

View File

@ -1 +0,0 @@
19

View File

@ -142,8 +142,7 @@ body > section {
display: inline-block;
font-size: 66%;
margin: 0 0.5rem;
max-width: 66%;
overflow: hidden;
max-width: 33%;
padding: 0 0.5rem;
white-space: nowrap; }
@ -251,23 +250,3 @@ body > section {
margin: 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; } } }
}

View File

@ -1,7 +1,6 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>What I am Doing</title>
<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'>
@ -18,10 +17,9 @@
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone.js" defer></script>
-->
<script src="js/personal-display-%VERSION%.js" type="text/javascript" defer></script>
<script src="js/personal-display.js" type="text/javascript" defer></script>
<meta name="viewport" content="width=device-width, user-scalable=no">
<meta name=version content="1.5">
</head>
<body>
<section id=current-task>
@ -32,22 +30,12 @@
<section id=priorities>
<h3>Next Actions (unsorted)</h3>
</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>
<form>
<h3>Configuration</h3>
<span class=validate-tips></span>
<section class=timestamper-config>
<span class=config-section-header>TimeStamper</span>
<div class=enabled><label>Enabled?</label>
<input type=checkbox class=enabled></div>
<div><label>Server Name: </label>
<input type=text class=host></div>
<div><label>Username: </label>
@ -61,8 +49,6 @@
</section>
<section class=gtd-config>
<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>
<input type=text class=host></div>
<div><label>Username: </label>
@ -77,7 +63,7 @@
<div class=button-panel>
<div class=global-config>
<label>Refresh (sec): </label>
<input type=text class=refresh-period></div>
<input type=text class=refresh></div>
<div class=save-button><a href="#">Save and Close</a></div>
</div>
<div class=wait-overlay><img src="img/loading-spinner.gif"><br><span></span></div>

View File

@ -2,7 +2,6 @@
var root = this;
var PD = root.PersonalDisplay = {};
PD.version = "1.5"
PD.hasHTML5LocalStorage = function() {
try {
@ -110,13 +109,12 @@
"change .gtd-config .category" : "addCategory",
"click .remove-button" : "removeCategory",
"click .save-button" : "saveAndClose",
"change input.enabled" : "enableDisable"},
"click .save-button" : "saveAndClose" },
initialize: function() {
_.bindAll(this, "addCategory", "enableDisable", "gtdLogin", "hide",
"loadGtdData", "loadTsData", "makeCategoryItem", "removeCategory",
"saveAndClose", "show", "tsLogin"); },
_.bindAll(this, "show", "hide", "tsLogin", "gtdLogin",
"loadTsData", "loadGtdData", "addCategory", "makeCategoryItem",
"removeCategory", "saveAndClose"); },
show: function() {
var $tsSection = this.$el.find(".timestamper-config");
@ -127,13 +125,11 @@
$tsSection.find(".username").val(PD.tsCfg.username);
$tsSection.find(".password").val(PD.tsCfg.password);
$tsSection.find(".host").val(PD.tsCfg.host);
$tsSection.find("input.enabled")[0].checked = PD.tsCfg.enabled;
if (PD.tsAuth) {
this.loadTsData(PD.tsCfg.host, PD.tsCfg.username); }
this.$el.find('.timeline').val(PD.tsCfg.timelineId);
this.enableDisable({target: $tsSection.find("input.enabled")[0]}); }
this.$el.find('.timeline').val(PD.tsCfg.timelineId); }
// Or suggest a default server.
else { $tsSection.find(".host").val("timestamper.jdb-labs.com"); }
@ -143,17 +139,14 @@
$gtdSection.find(".username").val(PD.gtdCfg.username);
$gtdSection.find(".password").val(PD.gtdCfg.password);
$gtdSection.find(".host").val(PD.gtdCfg.host);
$gtdSection.find("input.enabled")[0].checked = PD.gtdCfg.enabled;
if (PD.gtdAuth) { this.loadGtdData(PD.gtdCfg.host); }
// Create the items for the selected categories
$(".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-period').val(
this.$el.find('.refresh').val(
PD.refreshPeriod ? PD.refreshPeriod / 1000 : 15);
this.$el.fadeIn(); },
@ -164,7 +157,6 @@
var username = this.$el.find(".timestamper-config .username").val();
var password = this.$el.find(".timestamper-config .password").val();
var host = this.$el.find(".timestamper-config .host").val();
var thisView = this;
if (!PD.tsCfg) { PD.tsCfg = {}; }
@ -178,6 +170,7 @@
xhrFields: { withCredentials: true },
processData: false,
type: 'POST',
async: false,
data: JSON.stringify(
{"username": username, "password": password}),
@ -189,10 +182,7 @@
else { $(".validate-tips").text("There was an error " +
"trying to log into the TimeStamper service: " +
error); }
PD.tsAuth = false;
// Hide the wait overlay.
thisView.$el.find(".wait-overlay").fadeOut(); },
PD.tsAuth = false; },
success: function(data, textStatus, jqXHR) {
PD.tsAuth = true;
@ -201,18 +191,18 @@
// Load the user's timelines.
PD.configDialog.loadTsData(host, username);
// Hide the wait overlay.
thisView.$el.find(".wait-overlay").fadeOut(); }
}
});
// Success or failure we hide the wait overlay.
this.$el.find(".wait-overlay").fadeOut();
},
gtdLogin: function() {
var username = this.$el.find(".gtd-config .username").val();
var password = this.$el.find(".gtd-config .password").val();
var host = this.$el.find(".gtd-config .host").val();
var thisView = this;
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
@ -226,6 +216,7 @@
xhrFields: { withCredentials: true },
processData: false,
type: 'POST',
async: false,
data: JSON.stringify(
{"username": username, "password": password}),
@ -237,58 +228,48 @@
else { $(".validate-tips").text("There was an error " +
"trying to log into the Getting Things Done service: " +
error); }
PD.gtdAuth = false;
thisView.$el.find(".wait-overlay").fadeOut(); },
PD.gtdAuth = false; },
success: function(data, textStatus, jqXHR) {
PD.gtdAuth = true;
$(".validate-tips").text("");
PD.configDialog.loadGtdData(host);
thisView.$el.find(".wait-overlay").fadeOut(); }
PD.configDialog.loadGtdData(host); }
});
this.$el.find(".wait-overlay").fadeOut();
},
loadTsData: function(host, username) {
var thisView = this;
// (Re)load the user's timelines.
$.ajax({
PD.tsCfg.timelines = JSON.parse($.ajax({
url: 'https://' + host + '/ts_api/timelines/' + username,
xhrFields: { withCredentials: true },
success: function(data, textStatus, jqXHR) {
PD.tsCfg.timelines = data;
async: false}).responseText);
// Populate the available timelines list.
var $timelineSelectEl = $(".timestamper-config .timeline");
var $timelineSelectEl = this.$el.find(".timestamper-config .timeline");
$timelineSelectEl.empty();
_.forEach(PD.tsCfg.timelines, function(timeline) {
var $optionEl = $(document.createElement("option"));
$optionEl.attr("value", timeline.id);
$optionEl.text(timeline.description);
$timelineSelectEl.append($optionEl); });
}}); },
$timelineSelectEl.append($optionEl); }); },
loadGtdData: function(host) {
// Load the user's contexts
var contextLoaded = $.ajax({
PD.gtdCfg.contexts = JSON.parse($.ajax({
url: 'http://' + host + '/gtd/contexts',
xhrFields: { withCredentials: true },
success: function(data, textStatus, jqXHR) {
PD.gtdCfg.contexts = data;} });
async: false }).responseText);
// Load the user's projects
var projectsLoaded = $.ajax({
PD.gtdCfg.projects = JSON.parse($.ajax({
url: 'http://' + host + '/gtd/projects',
xhrFields: { withCredentials: true },
success: function(data, statuxText, jqXHR) {
PD.gtdCfg.projects = data;} });
async: false }).responseText);
$.when(contextLoaded, projectsLoaded).then(function() {
// Populate the available contexts and projects drop-down.
var $categorySelectEl = $(".gtd-config .category")
$categorySelectEl.empty();
@ -301,7 +282,7 @@
$optionEl.attr("value", category.id);
$optionEl.text(category.id);
$categorySelectEl.append($optionEl); });
$categorySelectEl[0].selectedIndex = 0; }); },
$categorySelectEl[0].selectedIndex = 0; },
makeCategoryItem: function(catName) {
var $liEl = $(
@ -320,18 +301,6 @@
removeCategory: function(source) {
$(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() {
if (!PD.tsCfg) { PD.tsCfg = {}; }
if (!PD.gtdCfg) { PD.gtdCfg = {}; }
@ -342,20 +311,18 @@
PD.tsCfg.username = $tsEl.find(".username").val();
PD.tsCfg.password = $tsEl.find(".password").val();
PD.tsCfg.timelineId = $tsEl.find(".timeline").val();
PD.tsCfg.enabled = $tsEl.find("input.enabled")[0].checked;
// Save Getting Things Done configuration.
var $gtdEl = this.$el.find(".gtd-config");
PD.gtdCfg.host = $gtdEl.find(".host").val();
PD.gtdCfg.username = $gtdEl.find(".username").val();
PD.gtdCfg.password = $gtdEl.find(".password").val();
PD.gtdCfg.enabled = $gtdEl.find("input.enabled")[0].checked;
PD.gtdCfg.categories = _.map(
this.$el.find(".category-name"),
function(span) { return $(span).text(); });
// Save global data
PD.refreshPeriod = parseInt(this.$el.find(".refresh-period").val()) * 1000;
PD.refreshPeriod = parseInt(this.$el.find(".refresh").val()) * 1000;
if (PD.hasHTML5LocalStorage()) {
localStorage.setItem("tsCfg", JSON.stringify(PD.tsCfg));
@ -363,22 +330,16 @@
localStorage.setItem("refreshPeriod",
JSON.stringify(PD.refreshPeriod)); }
this.hide(400, PD.main.refresh);
this.hide();
}
});
PD.Main = Backbone.View.extend({
el: $("body"),
events: {
"click a.refresh" : "refresh",
"click a.pause-continue" : "toggleSync",
"click a.show-config" : "showConfig",
"click a.toggle-fullscreen" : "toggleFullscreen" },
initialize: function() {
_.bindAll(this, "refresh", "toggleSync");
_.bindAll(this, "refresh");
// Create our config dialog view.
PD.configDialog = new PD.ConfigDialog();
@ -405,11 +366,10 @@
this.refresh();
// Schedule future refreshes.
PD.refreshIntervalId = setInterval(this.refresh, PD.refreshPeriod ? PD.refreshPeriod : 15000);
setInterval(this.refresh, PD.refreshPeriod ? PD.refreshPeriod : 15000);
},
refresh: function(evt) {
refresh: function() {
// If the dialog is still open we skip this sync to give the user
// a chance to finish configuration.
if ($("#config-dialog").is(":visible")) { return; }
@ -420,12 +380,13 @@
// Check that we are authenticated to the services we need. Try to
// authenticate if we are not.
if (PD.tsCfg.enabled && !PD.tsAuth) {
if (!PD.tsAuth) {
$.ajax({
url: "https://" + PD.tsCfg.host + "/ts_api/login",
xhrFields: { withCredentials: true },
processData: false,
type: "POST",
async: false,
data: JSON.stringify(
{ "username": PD.tsCfg.username,
@ -441,12 +402,13 @@
success: function(data, textStatus, jqXHR) {
PD.tsAuth = true; }}); }
if (PD.gtdCfg.enabled && !PD.gtdAuth) {
if (!PD.gtdAuth) {
$.ajax({
url: "http://" + PD.gtdCfg.host + "/gtd/login",
xhrFields: { withCredentials: true },
processData: false,
type: "POST",
async: false,
data: JSON.stringify(
{ "username": PD.gtdCfg.username,
@ -465,12 +427,9 @@
// Check that we have successfully authenticated to both services.
// If we are not, we will skip this refresh.
if ((PD.tsCfg.enabled && !PD.tsAuth) ||
(PD.gtdCfg.enabled && !PD.gtdAuth)) { return; }
if (!(PD.tsAuth && PD.gtdAuth)) { return; }
// Get the latest timestamp from the TimeStamper service.
if (PD.tsCfg.enabled) {
$("section#current-task").show();
$.ajax({
url: "https://" + PD.tsCfg.host + "/ts_api/entries/" +
PD.tsCfg.username + "/" + PD.tsCfg.timelineId,
@ -483,23 +442,19 @@
error: function(jqXHR, textStatus, errorText) {
if (jqXHR.status == 401) { PD.tsAuth = false; }
else {
alert("Unable to retrieve current timestamp: " +
errorText);
PD.configDialog.show(); } },
alert("Unable to retrieve current timestamp: " + errorText);
PD.configDialog.show(); }
},
success: function(data, textStatus, jqXHR) {
PD.currentActivityModel.set(data[0]); } }); }
// If the TimeStamper section is not enabled, hide the UI for it
else $("section#current-task").hide();
PD.currentActivityModel.set(data[0]); }
});
// Get the list of GTD entries for each of our categories.
if (PD.gtdCfg.enabled) {
var categories = _.reduce(
PD.gtdCfg.categories,
function(acc, cat) { return acc ? acc + "," + cat : cat; }, "");
$("section#priorities").show();
$.ajax({
url: "http://" + PD.gtdCfg.host + "/gtd/next-actions/" +
categories,
@ -512,9 +467,9 @@
if (jqXHR.status == 401) { PD.gtdAtuh = false; }
else if (jqXHR.status == 500) { return; }
else {
alert("Unable to retrieve next actions: " +
errorText);
PD.configDialog.show(); } },
alert("Unable to retrieve next actions: " + errorText);
PD.configDialog.show(); }
},
success: function(data, textStatus, jqXHR) {
var collection = PD.gtdNextActionCollection;
@ -534,54 +489,9 @@
// longer in our retrieved data and remove them.
collection.forEach(function(model) {
if (!_.any(data, model.equals)) {
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();
collection.remove(model); }});
}
});
}
});