Created
January 21, 2014 20:13
-
-
Save nterray/8547492 to your computer and use it in GitHub Desktop.
Dirty hack to group activities by categories in hamster (time tracker) exported report. Place this file in ~/.local/share/hamester-applet/ (adjust path accordingly to your distro)
This file contains 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 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
<meta name="author" content="hamster-applet" /> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"></script> | |
<link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/base/jquery-ui.css" rel="stylesheet" /> | |
<title>$title</title> | |
<style type="text/css"> | |
body { | |
font-family: "Droid Sans", "Liberation Sans", "Helvetica", "Arial", sans-serif; | |
font-size: 12px; | |
padding: 0; | |
margin: 0; | |
color: #303030; | |
background: #eee; | |
} | |
#content { | |
width: 700px; | |
padding: 24px 12px; | |
margin:0px auto; | |
background: #f6f6f6; | |
border-right: 2px solid #bbb; | |
border-left: 1px solid #bbb; | |
} | |
th, td { | |
text-align: left; | |
padding-right: 24px; | |
} | |
th { | |
padding-top: 12px; | |
} | |
h1 {margin-top: 0; margin-bottom: 1em;} | |
h2, h3 {margin-bottom: 4px;} | |
.even {background-color: #eee;} | |
.odd {background-color: #fff;} | |
.by_day_controls { | |
margin-bottom: 24px; | |
} | |
#activity_log { | |
display: none; | |
} | |
table.chart { | |
border-collapse:collapse; | |
margin-bottom: 2em; | |
} | |
td.bar_col { | |
width: 100px; | |
} | |
.bar { | |
background-color: #7B8ED7; | |
border-top-right-radius: 3px; | |
border-bottom-right-radius: 3px; | |
color: #fff; | |
height: 100%; | |
} | |
#date_chart { | |
width: 100%; | |
overflow: auto; | |
overflow-y: hidden; | |
height: 80px; | |
} | |
#date_chart table { | |
width: 100%; | |
height: 90%; | |
border-collapse: collapse; | |
margin-bottom: 4px; | |
} | |
#date_chart table tr {vertical-align: bottom;} | |
#date_chart table td { | |
padding: 0; | |
padding-right: 1px; | |
} | |
#date_chart .bar { | |
width: 100%; | |
background-color: #ccc; | |
border-radius: 0; | |
border-top-left-radius: 2px; | |
border-top-right-radius: 2px; | |
} | |
#grand_total { | |
color: #999; | |
} | |
#activity_log { | |
padding: 6px; | |
margin: 6px; | |
padding-left: 12px; | |
border: 1px solid silver; | |
background: #eee; | |
} | |
#date_facts tr:td { | |
padding-left: 24px; | |
} | |
p.template-instructions { | |
margin-top: 2em; | |
} | |
</style> | |
<style type="text/css" media="print"> | |
div#tabs ul { | |
display: none; | |
} | |
div#tabs { | |
border: none; | |
} | |
div.by_day_controls { | |
display: none; | |
} | |
p.template-instructions { | |
display: none; | |
} | |
</style> | |
<script type="text/javascript"> | |
var facts = $facts; | |
function showChartBy(target, data) { | |
for (var category in data) { | |
var section = $("<div><h3>" + category + "</h3></div>"); | |
target.append(section); | |
showChart(section, data[category]); | |
} | |
} | |
function showChart(target, data) { | |
totals = [] | |
// turn object into a list of tuples and convert durations from seconds to hours | |
var max_duration = 0; | |
for (var key in data) { | |
var duration = data[key] / 60 / 60.0; | |
totals.push([key, duration]); // hours | |
max_duration = Math.max(max_duration, duration); | |
} | |
// sort by duration descending | |
totals.sort(function compare(a,b) {return b[1] - a[1]}) | |
// create the HTML | |
var table = $("<table class='chart' style='width:100%' />") | |
for (var i=0; i < totals.length; i++) { | |
var total = totals[i]; | |
var row = $("<tr />"); | |
var label = $("<td />"); | |
label.text(total[0]); | |
row.append(label); | |
var duration = Math.round(total[1] * 10) / 10; // round to one decimal | |
var duration_label = $("<td />"); | |
duration_label.text(duration); | |
row.append(duration_label); | |
var bar_col = $("<td class='bar_col' />"); | |
var bar = $("<div class='bar'> </div>"); | |
bar.width(total[1] / max_duration * 100); | |
bar_col.append(bar); | |
row.append(bar_col); | |
table.append(row); | |
} | |
target.append(table); | |
} | |
$(document).ready(function() { | |
var categoryTotals = {}; | |
var activityTotals = {}; | |
var tagTotals = {}; | |
var dateTotals = {}; | |
var activitiesByCategories = {}; | |
function addBy(list, key, subkey, value) { | |
list[key] = list[key] || {}; | |
list[key][subkey] = list[key][subkey] || 0; | |
list[key][subkey] += value; | |
} | |
function add(list, key, value) { | |
list[key] = list[key] || 0; | |
list[key] += value; | |
} | |
var grandTotal = 0; | |
for (var i=0; i < facts.length; i++) { | |
var fact = facts[i]; | |
add(dateTotals, fact.date, fact.delta) | |
add(categoryTotals, fact.category, fact.delta) | |
add(activityTotals, fact.activity, fact.delta) | |
addBy(activitiesByCategories, fact.category, fact.activity, fact.delta) | |
for (var j=0; j < fact.tags.length; j++) { | |
add(tagTotals, fact.tags[j], fact.delta) | |
} | |
grandTotal += fact.delta; | |
} | |
grandTotal = Math.round(grandTotal / 60 / 60 * 10) / 10; | |
$("#grand_total").text("(" + grandTotal + ")"); | |
showChart($("#category_chart"), categoryTotals) | |
showChart($("#activity_chart"), activityTotals) | |
showChart($("#tag_chart"), tagTotals) | |
showChartBy($("#activity_by_category_chart"), activitiesByCategories) | |
// create the by-day chart | |
var startDate = $start_date; | |
var endDate = $end_date; | |
var dates = []; | |
var dateMax = 0; | |
for (var i=startDate; i <= endDate; i += 24 * 60 * 60) { | |
var duration = dateTotals[i] || 0; | |
dateMax = Math.max(dateMax, duration); | |
dates.push([new Date(i), duration]) | |
} | |
var table = $("<table />") | |
var row = $("<tr />"); | |
for (var i=0; i<dates.length; i++) { | |
var date = dates[i]; | |
var col = $("<td />"); | |
var bar = $("<div class='bar'> </div>"); | |
var bar_height = date[1] / dateMax * 70; | |
if (bar_height < 1) | |
bar.height(1); | |
else | |
bar.height(bar_height) | |
col.append(bar); | |
row.append(col); | |
} | |
table.append(row); | |
$("#date_chart").append(table); | |
$("#activity_log_link").click(function() { | |
$("#activity_log").toggle() | |
}) | |
$("#show_details").click(function() { | |
if ($(this).attr("checked")) { | |
$(".by_date_row").show(); | |
} else { | |
$(".by_date_row").hide(); | |
} | |
}) | |
$("#show_totals").click(function() { | |
if ($(this).attr("checked")) { | |
$(".by_date_total_row").show(); | |
} else { | |
$(".by_date_total_row").hide(); | |
} | |
}) | |
populateFactTable(); | |
$(".by_day_controls input").click(function(){ | |
populateFactTable(); | |
}); | |
}); | |
function populateFactTable() { | |
// fill fact rows | |
var table = $("#date_facts"); | |
table.empty(); | |
var dateFacts = $date_facts; | |
// determine if we will be doing any internal counting | |
var keys = []; | |
if ($("#show_activities").attr("checked")) | |
keys.push("activity"); | |
if ($("#show_categories").attr("checked")) | |
keys.push("category"); | |
if ($("#show_tags").attr("checked")) | |
keys.push("tags"); | |
for (var i in dateFacts) { | |
var dateString = dateFacts[i][0]; | |
var dateTotal = 0; | |
var factTotals = {} | |
for (var j in dateFacts[i][1]) { | |
var fact = dateFacts[i][1][j]; | |
fact.tags = fact.tags.join(", "); | |
if (keys.length > 0) { | |
var key = []; | |
for (var k in keys) { | |
key.push(fact[keys[k]]) | |
} | |
key = key.join(" - "); | |
factTotals[key] = factTotals[key] || 0; | |
factTotals[key] += fact.delta; | |
} | |
dateTotal += fact.delta; | |
} | |
dateTotal = Math.round(dateTotal / 60 / 60 * 10) / 10; | |
table.append("<tr><th>" + dateString + "</th><th>" + dateTotal +"</th></tr>"); | |
for (var key in factTotals) { | |
keyTotal = Math.round(factTotals[key] / 60 / 60 * 10) / 10; | |
table.append("<tr><td>" + key + "</td><td>" + keyTotal +"</td></tr>"); | |
} | |
} | |
} | |
</script> | |
</head> | |
<body> | |
<div id="content"> | |
<h1>$title <span id="grand_total"></span></h1> | |
<div id="date_chart"></div> | |
<a id="activity_log_link" href="javascript: false">Show activity log</a> | |
<div id="activity_log"> | |
<h2>$activity_log_title</h2> | |
<table> | |
<tr> | |
<th>$header_date</th> | |
<th>$header_activity</th> | |
<th>$header_category</th> | |
<th>$header_tags</th> | |
<th>$header_start</th> | |
<th>$header_end</th> | |
<th>$header_duration</th> | |
<th>$header_description</th> | |
</tr> | |
<all_activities> | |
<tr> | |
<td> | |
<!-- there is also date_iso --> | |
$date | |
</td> | |
<td>$activity</td> | |
<td>$category</td> | |
<td>$tags</td> | |
<td> | |
<!-- there is also start_iso --> | |
$start | |
</td> | |
<td> | |
<!-- there is also end_iso --> | |
$end | |
</td> | |
<td> | |
<!-- there is also duration_decimal and duration_minutes --> | |
$duration | |
</td> | |
<td>$description</td> | |
</tr> | |
</all_activities> | |
</table> | |
</div> | |
<table> | |
<tr style="vertical-align: top"> | |
<td style="width: 100%"> | |
<h2>$totals_by_day_title</h2> | |
<div class="by_day_controls"> | |
$show_prompt | |
<input type="checkbox" id="show_activities" checked="checked"></input> | |
<label for="show_details">$activity_totals_heading</label> | |
<input type="checkbox" id="show_categories" checked="checked"></input> | |
<label for="show_totals">$category_totals_heading</label> | |
<input type="checkbox" id="show_tags" checked="checked"></input> | |
<label for="show_totals">$tag_totals_heading</label> | |
</div> | |
<table id="date_facts"></table> | |
</td> | |
<td> | |
<div> | |
<h2>Categories</h2> | |
<div id="category_chart"></div> | |
</div> | |
<div> | |
<h2>Activities</h2> | |
<div id="activity_chart"></div> | |
</div> | |
<div> | |
<h2>Activities by Categories</h2> | |
<div id="activity_by_category_chart"></div> | |
</div> | |
<div> | |
<h2>Tags</h2> | |
<div id="tag_chart"></div> | |
</div> | |
</td> | |
</tr> | |
</table> | |
<p class="template-instructions"> | |
<a href="file:///$data_dir/report_template.html">$show_template</a>. | |
$template_instructions. | |
</p> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment