Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created October 23, 2017 11:21
Show Gist options
  • Save arturaz/6d7dc66b03c9feea9d5d1e472187d631 to your computer and use it in GitHub Desktop.
Save arturaz/6d7dc66b03c9feea9d5d1e472187d631 to your computer and use it in GitHub Desktop.
<!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