[hamster-applet] giving some love to the reports. work in progress
- From: Toms Baugis <tbaugis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hamster-applet] giving some love to the reports. work in progress
- Date: Sat, 6 Nov 2010 12:49:47 +0000 (UTC)
commit c65e6dff88865e581b25a13178d32a7b50a9421c
Author: Toms Bauģis <toms baugis gmail com>
Date: Sat Nov 6 12:49:29 2010 +0000
giving some love to the reports. work in progress
data/report_template.html | 402 ++++++++++++++++++++++++++++++++-------------
src/hamster/reports.py | 7 +
2 files changed, 295 insertions(+), 114 deletions(-)
---
diff --git a/data/report_template.html b/data/report_template.html
index 0485ed4..e5700cd 100644
--- a/data/report_template.html
+++ b/data/report_template.html
@@ -12,16 +12,12 @@
<title>$title</title>
<style type="text/css">
body {
- font-family: "sans-serif";
+ font-family: "Droid Sans", "Liberation Sans", "Helvetica", "Arial", sans-serif;
font-size: 12px;
padding: 12px;
color: #303030;
}
- h2 {
- margin-top: 2em;
- border-bottom: 2px solid #303030;
- }
th, td {
text-align: left;
padding-right: 24px;
@@ -31,12 +27,73 @@
padding-top: 12px;
}
+ h1 {margin-top: 0; margin-bottom: 1em;}
+ h2 {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 table {
+ width: 100%;
+ 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: 3px;
+ border-top-right-radius: 3px;
+ }
+
+ .duration {
+ color: #999;
+ }
+
+ #activity_log {
+ padding: 6px;
+ margin: 6px;
+ padding-left: 12px;
+ border: 1px solid silver;
+ background: #eee;
+
+ }
</style>
<style type="text/css" media="print">
@@ -58,8 +115,117 @@
</style>
<script type="text/javascript">
+ var facts = $facts;
+
+ 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() {
- $("#tabs").tabs()
+ var categoryTotals = {};
+ var activityTotals = {};
+ var tagTotals = {};
+ var dateTotals = {}
+
+ function add(list, key, value) {
+ list[key] = list[key] || 0;
+ list[key] += value;
+ }
+
+ 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)
+
+ for (var j=0; j < fact.tags.length; j++) {
+ add(tagTotals, fact.tags[j], fact.delta)
+ }
+ }
+
+ showChart($("#category_chart"), categoryTotals)
+ showChart($("#activity_chart"), activityTotals)
+ showChart($("#tag_chart"), tagTotals)
+
+
+ // 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 * 100;
+ if (bar_height < 1)
+ bar.height("1px");
+ 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")) {
@@ -84,120 +250,128 @@
</head>
<body>
-<h1>$title</h1>
+<h1>$title <span class="duration">(<totals_activity>$total_duration</totals_activity>)</span></h1>
-<div id="tabs">
- <ul>
- <li><a href="#tabs-1">$totals_title</a></li>
- <li><a href="#tabs-2">$activity_log_title</a></li>
- </ul>
- <div id="tabs-1">
- <h2>$totals_title</h2>
- <table>
- <tr>
- <th>$header_category</th>
- <th>$header_activity</th>
- <th>$header_duration</th>
- </tr>
- <by_activity_category>
- <tr><td>$category</td><td>$activity</td><td>$duration</td></tr>
- </by_activity_category>
- <totals_activity>
- <tr><th colspan="2" style="text-align:right;">$total_row</th><th>$total_duration</th></tr>
- </totals_activity>
- </table>
-
- <h2>$totals_by_day_title</h2>
-
- <div class="by_day_controls">
- $show_prompt
- <input type="checkbox" id="show_details" checked="checked"></input>
- <label for="show_details">$activity_totals_heading</label>
-
- <input type="checkbox" id="show_totals" checked="checked"></input>
- <label for="show_totals">$category_totals_heading</label>
- </div>
-
- <table>
- <tr>
- <th>Date</th>
- <th class="by_date_row">$activity_totals_heading</th>
- <th class="by_date_total_row">$category_totals_heading</th>
- </tr>
+<div id="date_chart"></div>
- <by_date>
- <tr valign="top">
- <td>$date</td>
- <td class="by_date_row">
- <table width="100%">
- <by_date_activity>
- <tr>
- <td>$activity ($category)</td>
- <td style="text-align: right">
- <!-- there is also duration_decimal and duration_minutes -->
- $duration
- </td>
- </tr>
- </by_date_activity>
- </table>
- </td>
- <td class="by_date_total_row">
- <table width="100%">
- <by_date_category>
- <tr>
- <td>$category</td>
- <td style="text-align: right">
- <!-- there is also duration_decimal and duration_minutes -->
- $duration
- </td>
- </tr>
- </by_date_category>
- </table>
- </td>
- </tr>
- <tr><td colspan="3"> </td></tr>
- </by_date>
- </table>
- </div>
- <div id="tabs-2">
- <table>
+<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>
- <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>
+ <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>
+ </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_details" checked="checked"></input>
+ <label for="show_details">$activity_totals_heading</label>
+
+ <input type="checkbox" id="show_totals" checked="checked"></input>
+ <label for="show_totals">$category_totals_heading</label>
+ </div>
+
+ <table>
<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>
+ <th>Date</th>
+ <th class="by_date_row">$activity_totals_heading</th>
+ <th class="by_date_total_row">$category_totals_heading</th>
</tr>
- </all_activities>
- </table>
- </div>
-</div>
+
+ <by_date>
+ <tr valign="top">
+ <td>$date</td>
+ <td class="by_date_row">
+ <table width="100%">
+ <by_date_activity>
+ <tr>
+ <td>$activity ($category)</td>
+ <td style="text-align: right">
+ <!-- there is also duration_decimal and duration_minutes -->
+ $duration
+ </td>
+ </tr>
+ </by_date_activity>
+ </table>
+ </td>
+ <td class="by_date_total_row">
+ <table width="100%">
+ <by_date_category>
+ <tr>
+ <td>$category</td>
+ <td style="text-align: right">
+ <!-- there is also duration_decimal and duration_minutes -->
+ $duration
+ </td>
+ </tr>
+ </by_date_category>
+ </table>
+ </td>
+ </tr>
+ <tr><td colspan="3"> </td></tr>
+ </by_date>
+ </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>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.
diff --git a/src/hamster/reports.py b/src/hamster/reports.py
index f1a2253..152fe6a 100644
--- a/src/hamster/reports.py
+++ b/src/hamster/reports.py
@@ -31,6 +31,8 @@ from configuration import runtime
from utils import stuff, trophies
from utils.i18n import C_
+from calendar import timegm
+
def simple(facts, start_date, end_date, format, path):
facts = copy.deepcopy(facts) # dont want to do anything bad to the input
report_path = stuff.locale_from_utf8(path)
@@ -179,6 +181,7 @@ class XMLWriter(ReportWriter):
class HTMLWriter(ReportWriter):
def __init__(self, path, start_date, end_date):
ReportWriter.__init__(self, path, datetime_format = None)
+ self.start_date, self.end_date = start_date, end_date
dates_dict = stuff.dateDict(start_date, "start_")
dates_dict.update(stuff.dateDict(end_date, "end_"))
@@ -376,6 +379,10 @@ class HTMLWriter(ReportWriter):
show_template = _("Show template"),
template_instructions = _("You can override it by storing your version in %(home_folder)s") % {'home_folder': runtime.home_data_dir},
+ start_date = timegm(self.start_date.timetuple()),
+ end_date = timegm(self.end_date.timetuple()),
+ facts = [dict(fact) for fact in facts],
+
all_activities_rows = "\n".join(self.fact_rows),
by_date_rows = "\n".join(by_date),
by_activity_category_rows = "\n".join(by_activity_category_rows),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]