[hamster-applet] dynamic totals.



commit 60e1fe49831de3395f8dff138c9a6c6b3f572f86
Author: Toms Bauģis <toms baugis gmail com>
Date:   Sun Nov 7 22:27:58 2010 +0000

    dynamic totals.

 data/report_template.html |  298 ++++++++++++++++++++++++++-------------------
 src/hamster/reports.py    |  116 ++++--------------
 2 files changed, 196 insertions(+), 218 deletions(-)
---
diff --git a/data/report_template.html b/data/report_template.html
index e5700cd..5e09779 100644
--- a/data/report_template.html
+++ b/data/report_template.html
@@ -14,8 +14,19 @@
         body {
             font-family: "Droid Sans", "Liberation Sans", "Helvetica", "Arial", sans-serif;
             font-size: 12px;
-            padding: 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 {
@@ -59,16 +70,21 @@
             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 tr {vertical-align: bottom;}
         #date_chart table td {
             padding: 0;
             padding-right: 1px;
@@ -78,8 +94,8 @@
             width: 100%;
             background-color: #ccc;
             border-radius: 0;
-            border-top-left-radius: 3px;
-            border-top-right-radius: 3px;
+            border-top-left-radius: 2px;
+            border-top-right-radius: 2px;
         }
 
         .duration {
@@ -94,6 +110,10 @@
             background: #eee;
 
         }
+
+        #date_facts tr:td {
+            padding-left: 24px;
+        }
     </style>
 
     <style type="text/css" media="print">
@@ -213,7 +233,7 @@
                 if (bar_height < 1)
                     bar.height("1px");
                 else
-                    bar.height(bar_height)
+                    bar.height(bar_height +"%")
 
                 col.append(bar);
                 row.append(col);
@@ -245,136 +265,166 @@
 
 
             })
+
+            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>
 
-<h1>$title <span class="duration">(<totals_activity>$total_duration</totals_activity>)</span></h1>
+<div id="content">
+    <h1>$title <span class="duration">($grand_total)</span></h1>
 
-<div id="date_chart"></div>
+    <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>
+    <a id="activity_log_link" href="javascript: false">Show activity log</a>
+    <div id="activity_log">
+        <h2>$activity_log_title</h2>
+        <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>$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>
-    </table>
-</div>
-
-
+            <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_details" checked="checked"></input>
-                <label for="show_details">$activity_totals_heading</label>
+    <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>Tags</h2>
+                    <div id="tag_chart"></div>
+                </div>
+            </td>
+        </tr>
+    </table>
 
-                <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>
 
-                <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">&nbsp;</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.
-</p>
+    <p class="template-instructions">
+        <a href="file:///$data_dir/report_template.html">$show_template</a>.
+        $template_instructions.
+    </p>
+</div>
 </body>
 </html>
diff --git a/src/hamster/reports.py b/src/hamster/reports.py
index 152fe6a..5e8bfb5 100644
--- a/src/hamster/reports.py
+++ b/src/hamster/reports.py
@@ -211,9 +211,6 @@ class HTMLWriter(ReportWriter):
         self.fact_row_template = self._extract_template('all_activities')
 
         self.by_date_row_template = self._extract_template('by_date_activity')
-        self.by_date_total_row_template = self._extract_template("by_date_category")
-        self.by_activity_category_row_template = self._extract_template("by_activity_category")
-        self.totals_row_template = self._extract_template("totals_activity")
 
         self.by_date_template = self._extract_template('by_date')
 
@@ -266,105 +263,38 @@ class HTMLWriter(ReportWriter):
 
 
     def _finish(self, report, facts):
-        # group by date
-        name_category = lambda fact: (fact.category, fact.activity)
 
+        # group by date
         by_date = []
         for date, date_facts in itertools.groupby(facts, lambda fact:fact.date):
-            by_name = sorted(date_facts, key=name_category)
-
-            by_date_rows = []
-            for (category, activity), ac_facts in itertools.groupby(by_name, name_category):
-                duration = dt.timedelta()
-                for fact in ac_facts:
-                    duration += fact.delta
-
-
-                by_date_rows.append(Template(self.by_date_row_template).safe_substitute(
-                                    dict(activity = activity,
-                                         category = category,
-                                         duration = stuff.format_duration(duration),
-                                         duration_minutes = "%d" % (stuff.duration_minutes(fact.delta)),
-                                         duration_decimal = "%.2f" % (stuff.duration_minutes(fact.delta) / 60.0),
-                                        )
-                                    ))
-
-            by_date_total_rows = []
-            for category, c_facts in itertools.groupby(by_name, lambda fact:fact.category):
-                duration = dt.timedelta()
-                for fact in c_facts:
-                    duration += fact.delta
-
-
-                by_date_total_rows.append(Template(self.by_date_total_row_template).safe_substitute(
-                                          dict(category = category,
-                                               duration = stuff.format_duration(duration),
-                                               duration_minutes = "%d" % (stuff.duration_minutes(fact.delta)),
-                                               duration_decimal = "%.2f" % (stuff.duration_minutes(fact.delta) / 60.0),
-                                              )
-                                          ))
-
-
-            res = Template(self.by_date_template).safe_substitute(
-                           dict(date = fact.date.strftime(
-                                       # date column format for each row in HTML report
-                                       # Using python datetime formatting syntax. See:
-                                       # http://docs.python.org/library/time.html#time.strftime
-                                       C_("html report","%b %d, %Y")),
-                                by_date_activity_rows = "\n".join(by_date_rows),
-                                by_date_category_rows = "\n".join(by_date_total_rows)
-                           ))
-            by_date.append(res)
-
-        by_activity_category_rows = []
-        # group by activity
-        name_category = lambda fact: (fact.category)
-        name_activity = lambda fact: (fact.activity)
-
-        total_duration = None
-        by_category = sorted(facts, key=name_category)
-        for category, category_facts in itertools.groupby(by_category, lambda fact:fact.category):
-            by_activity = sorted(category_facts, key=name_activity)
-
-            for (activity), ac_facts in itertools.groupby(by_activity, name_activity):
-                duration = dt.timedelta()
-                for fact in ac_facts:
-                    duration += fact.delta
-
-                by_activity_category_rows.append(Template(self.by_activity_category_row_template).safe_substitute(
-                                        dict(activity = activity,
-                                             category = category,
-                                             duration = stuff.format_duration(duration),
-                                             duration_minutes = "%d" % (stuff.duration_minutes(fact.delta)),
-                                             duration_decimal = "%.2f" % (stuff.duration_minutes(fact.delta) / 60.0),
-                                        )
-                                    ))
-                if (total_duration):
-                    total_duration += duration
-                else:
-                    total_duration = duration
-
-        by_totals_rows = []
-        if (len(by_activity_category_rows) > 0):
-            by_totals_rows.append(Template(self.totals_row_template).safe_substitute(
-                                  dict(total_duration = stuff.format_duration(total_duration),
-                                         total_duration_minutes = "%d" % (stuff.duration_minutes(total_duration)),
-                                         total_duration_decimal = "%.2f" % (stuff.duration_minutes(total_duration) / 60.0),
-                                         total_row = _("Total")
-                                    )
-                                ))
+            by_date.append((date, [dict(fact) for fact in date_facts]))
+        by_date = dict(by_date)
+
+        date_facts = []
+        date = self.start_date
+        while date <= self.end_date:
+            str_date = date.strftime(
+                        # date column format for each row in HTML report
+                        # Using python datetime formatting syntax. See:
+                        # http://docs.python.org/library/time.html#time.strftime
+                        C_("html report","%b %d, %Y"))
+            date_facts.append([str_date, by_date.get(date, [])])
+            date += dt.timedelta(days=1)
 
 
         data = dict(
             title = self.title,
+            #grand_total = _("%s hours") % ("%.1f" % (total_duration.seconds / 60.0 / 60 + total_duration.days * 24)),
+
             totals_by_day_title = _("Totals by Day"),
             activity_log_title = _("Activity Log"),
             totals_title = _("Totals"),
 
-            activity_totals_heading = _("totals by activity"),
-            category_totals_heading = _("totals by category"),
+            activity_totals_heading = _("activities"),
+            category_totals_heading = _("categories"),
+            tag_totals_heading = _("tags"),
 
-            show_prompt = _("Show:"),
+            show_prompt = _("Distinguish:"),
 
             header_date = _("Date"),
             header_activity = _("Activity"),
@@ -382,11 +312,9 @@ class HTMLWriter(ReportWriter):
             start_date = timegm(self.start_date.timetuple()),
             end_date = timegm(self.end_date.timetuple()),
             facts = [dict(fact) for fact in facts],
+            date_facts = date_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),
-            totals_activity_rows = "\n".join(by_totals_rows)
+            all_activities_rows = "\n".join(self.fact_rows)
         )
         report.write(Template(self.main_template).safe_substitute(data))
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]