Created
October 23, 2017 11:21
-
-
Save arturaz/6d7dc66b03c9feea9d5d1e472187d631 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Tiny Lab Productions Projects</title> | |
<style> | |
html, body { | |
height: 100%; | |
margin: 0; | |
} | |
#holder { | |
min-height: 100%; | |
} | |
#holder table { | |
padding: 10px; | |
height:100%; | |
width:100%; | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
left: 0; | |
right: 0; | |
table-layout: fixed | |
} | |
table td { | |
border: 1px solid lightgray; | |
} | |
.chart { | |
} | |
</style> | |
<script src="https://code.jquery.com/jquery-3.2.1.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.bundle.js"></script> | |
<script src="http://underscorejs.org/underscore.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script> | |
<!--[if lt IE 9]> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script> | |
<![endif]--> | |
</head> | |
<body> | |
<div id="holder"></div> | |
<script> | |
$.urlParam = function(name) { | |
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); | |
if (results == null) return null; | |
else return decodeURI(results[1]) || 0; | |
} | |
var apiKey = $.urlParam("apiKey"); | |
var server = $.urlParam("server"); | |
var refreshEvery = $.urlParam("refreshEvery") || 0; | |
var holder = document.getElementById("holder"); | |
function req(resource, data, onSuccess) { | |
return $.ajax({ | |
url: "http://" + server + "/" + resource, | |
data: data, | |
method: "GET", | |
dataType: "json", | |
headers: { | |
"Authorization": "Basic " + btoa(apiKey + ":") | |
}, | |
success: onSuccess | |
}) | |
} | |
function processTags(resp) { | |
return resp.tags.map(tag => { | |
var matched = tag.name.match(/^G(\d+)?\s*:\s*(.+)$/); | |
if (matched == null) return null; | |
else return {id: parseInt(tag.id), name: matched[2], order: parseInt(matched[1]) || 0}; | |
}).filter(tag => tag != null) | |
} | |
function processTasks(tags) { return function(resp) { | |
console.log(resp); | |
var tasks = resp["todo-items"].map(task => { | |
var late = false; | |
if (!task.completed) { | |
var dd = task["due-date"]; | |
if (dd != "" && dd != null) | |
late = Date.now() >= Date.parse(dd); | |
} | |
return { | |
project: task["project-name"], | |
completed: task.completed, | |
late: late, | |
tags: task.tags | |
}; | |
}); | |
var datum = tags.map(tag => ({ | |
tag: tag, | |
projects: Immutable.Map(_.groupBy( | |
tasks.filter(task => task.tags.find(tTag => tag.id === tTag.id)), | |
task => task.project | |
)).entrySeq().map(kv => { | |
var name = kv[0]; | |
var tasks = kv[1]; | |
var stats = | |
Immutable.Map(_.countBy(tasks, task => { | |
if (task.completed) return "completed"; | |
if (task.late) return "late"; | |
return "incomplete"; | |
})) | |
.update("completed", v => v || 0) | |
.update("incomplete", v => v || 0) | |
.update("late", v => v || 0) | |
.set("name", name); | |
return stats | |
.set("total", tasks.length) | |
.set("completed_pct", stats.get("completed") / stats.get("total")); | |
}) | |
})).filter(goal => { | |
var maxIncomplete = _.max(goal.projects.map(stats => stats.get("incomplete")).toArray()); | |
return maxIncomplete > 0; | |
}); | |
return _.sortBy(datum, data => data.tag.order); | |
}; } | |
function toChartData(data) { | |
function mapProp(name) { return data.projects.map(project => project.get(name)).toArray(); } | |
return { | |
"labels": mapProp("name"), | |
"datasets": [ | |
{ | |
label: "Total Tasks", | |
data: mapProp("total"), | |
fill: true, | |
"backgroundColor": "rgba(91, 153, 239, 0.2)", | |
"borderColor": "rgb(3, 70, 163)", | |
"borderWidth": 1 | |
}, | |
{ | |
label: "Completed Tasks", | |
data: mapProp("completed"), | |
fill: true, | |
"backgroundColor": "rgba(172, 244, 4, 0.2)", | |
"borderColor": "rgb(56, 76, 9)", | |
"borderWidth": 1 | |
}, | |
{ | |
label: "Late Tasks", | |
data: mapProp("late"), | |
fill: true, | |
"backgroundColor": "rgba(252, 65, 65, 0.2)", | |
"borderColor": "rgb(153, 0, 0)", | |
"borderWidth": 1 | |
}, | |
] | |
} | |
} | |
function update() { | |
req("tags.json") | |
.then(processTags) | |
.then(tags => | |
req("tasks.json", { | |
"tag-ids": tags.map(tag => tag.id).join(","), | |
includeCompletedTasks: true, | |
includeCompletedSubtasks: true, | |
pageSize: 250 | |
}).then(processTasks(tags)) | |
) | |
.done(result => { | |
console.log(result); | |
var dim = Math.ceil(Math.sqrt(result.length)); | |
var table = document.createElement("table"); | |
for (var row = 0; row < dim; row++) { | |
if (result.length - 1 >= row * dim) { | |
var tr = document.createElement("tr"); | |
for (var col = 0; col < dim; col++) { | |
var idx = row * dim + col; | |
var elem = result[idx]; | |
if (elem) { | |
var td = document.createElement("td"); | |
td.setAttribute("style", "height: " + (100 / dim) + "%; overflow: hidden;") | |
var ctx = document.createElement("canvas"); | |
td.appendChild(ctx); | |
var myChart = new Chart(ctx, { | |
type: 'horizontalBar', | |
"data": toChartData(elem), | |
"options": { | |
maintainAspectRatio: false, | |
title: { | |
display: true, | |
position: "top", | |
fontSize: 8 + (24 / dim), | |
fontColor: 'black', | |
text: elem.tag.name | |
}, | |
legend: { | |
position: "bottom" | |
}, | |
scales: {"xAxes":[{"ticks":{"beginAtZero":true}}]} | |
} | |
}); | |
tr.appendChild(td); | |
} | |
} | |
} | |
table.appendChild(tr); | |
} | |
holder.innerHTML = ""; | |
holder.appendChild(table); | |
if (refreshEvery > 0) window.setTimeout(update, refreshEvery * 1000); | |
}); | |
} | |
update(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment