changeset 135:57dbb265a02a

Make activity view to work.
author Daniele Nicolodi <daniele@grinta.net>
date Fri, 14 Oct 2011 22:02:41 +0200
parents 5757ae81d57e
children 66b8360a41c9
files src/ltpdarepo/__init__.py src/ltpdarepo/static/style.css src/ltpdarepo/templates/activity.html src/ltpdarepo/templates/database.html src/ltpdarepo/views/activity.py
diffstat 5 files changed, 89 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/src/ltpdarepo/__init__.py	Fri Oct 14 21:59:42 2011 +0200
+++ b/src/ltpdarepo/__init__.py	Fri Oct 14 22:02:41 2011 +0200
@@ -127,6 +127,9 @@
 from .views.browse import module
 app.register_blueprint(module, url_prefix='/browse')
 
+from .views.activity import module
+app.register_blueprint(module, url_prefix='/browse')
+
 from .views.profile import module
 app.register_blueprint(module, url_prefix='/user')
 
--- a/src/ltpdarepo/static/style.css	Fri Oct 14 21:59:42 2011 +0200
+++ b/src/ltpdarepo/static/style.css	Fri Oct 14 22:02:41 2011 +0200
@@ -355,7 +355,12 @@
 /* activity view */
 
 .activity {
-    margin: 1em;
+    border: 1px solid #CCC;
+    padding: 2px;
+    margin: 0;
+    box-shadow: 0px 0px 2px #DDD;
+    -moz-box-shadow: 0px 0px 2px #DDD;
+    -webkit-box-shadow: 0px 0px 2px #DDD;
 }
 
 .activity table {
@@ -365,13 +370,25 @@
 
 .activity td {
     margin: 0;
-    padding: 0.3em;
+    padding: 4px 0;
     border: none;
     font-size: 90%;
 }
 
+.activity td span.num {
+    display: inline-block;
+    width: 2em;
+    visibility: hidden;
+}
+
+.activity td:hover span.num {
+    visibility: visible;
+    color: red;
+}
+
 .activity td.bars {
-    padding: 0 2px;
+    padding: 0 1px;
+    margin: 0;
     vertical-align: bottom;
 }
 
@@ -381,6 +398,31 @@
     width: 100%;
 }
 
+.monthes {
+    float: right;
+    font-size: 90%;
+}
+
+.monthes a, .monthes span {
+    text-align: center;
+    text-decoration: none;
+    color: #888;
+    display: inline-block;
+    float: left;
+    padding: 0px;
+    margin: 5px;
+    border-bottom: 1px solid white;
+}
+
+.monthes a:hover {
+    border-bottom: 1px solid #888;
+}
+
+.day {
+    color: #888;
+    font-size: 90%;
+}
+
 /* search form */
 
 .search {
--- a/src/ltpdarepo/templates/activity.html	Fri Oct 14 21:59:42 2011 +0200
+++ b/src/ltpdarepo/templates/activity.html	Fri Oct 14 22:02:41 2011 +0200
@@ -1,57 +1,32 @@
 {% extends "layout.html" %}
 {% block title %}{{ database.id }}{% endblock %}
-{% block head %}
-    <script type="text/javascript" src="/static/jquery-1.6.1.min.js"></script>
-    <script type="text/javascript" src="/static/draw.js"></script>
-{% endblock %}
 {% block body %}
 <h2>Database &#x00AB;{{ database.id }}&#x00BB;</h2>
 <p class="discrete">{{ database.description }}</p>
-{#
+<p class="discrete">Objects submitted per day in <em>{{ curr.strftime('%B %Y') }}</em></p>
 <div class="wrapper">
-  <canvas width="100%" height="200" id="c"></canvas>
+  <div class="monthes wrapper">
+    <a title="{{ prev.strftime('%B %Y') }}" href="{{ url_for('activity.activity', database=database.id, date=prev) }}">prev</a>
+    <a title="{{ next.strftime('%B %Y') }}" href="{{ url_for('activity.activity', database=database.id, date=next) }}">next</a>
+    <a href="{{ url_for('activity.activity', database=database.id) }}">today</a>
+  </div>
 </div>
-<script type="text/javascript">
-  var activity = {{ activity|tojson|safe }}
-  var canvas = document.getElementById("c");
-  canvas.width = canvas.parentNode.clientWidth;
-  var context = canvas.getContext("2d");
-  var sep = 3;
-  var width = Math.floor((canvas.width - sep * activity.length)/ activity.length);
-  var nmax = 300;
-  var height = canvas.height / nmax;
-  context.fillStyle = "#DDD";
-  for (var i=0; i < activity.length; i++) {
-    context.fillRect((width+sep)*i, canvas.height, width, -1*activity[i][1]*height);
-  }
-</script>
-#}
-<div class="activity">
+<div class="activity" style="">
   <table>
     <tr>
-      <td></td>
       {% set nmax = 300 %}
-      {% for when, n in activity %}
-      {% set height = n * 300 / nmax %} 
-      <td class="bars" style="height: 300px;"><div style="height: {{height}}px;">&nbsp;</div></td>
+      {% for day, num in activity %}
+      {% set height = num * 300 / nmax %} 
+      <td class="bars" style="height: 300px;">
+        <span class="num">{{ num }}</span><div style="height: {{height}}px;">&nbsp;</div>
+      </td>
       {% endfor %}
-      <td></td>
     </tr>
     <tr>
-      <td><a href="">&#x00AB;</a></td>
-      {% for when, number in activity %}
-      <td><a href="">{{ when }}</a></td>
+      {% for when, num in activity %}
+      <td><a class="day" href="{{ url_for('browse.query', database=database.id, field=('submitted', 'submitted'), operator=('>', '<'), value=(when, when + dt)) }}">{{ when.strftime('%d') }}</a></td>
       {% endfor %}
-      <td><a href="">&#x00BB;</a></td>
     </tr>
   </table>
 </div>
-
-{#
-<ul>
-  {% for when, number in activity %}
-  <li>{{ when }}: {{ number }}</li>
-  {% endfor %}
-</ul>
-#}
 {% endblock %}
--- a/src/ltpdarepo/templates/database.html	Fri Oct 14 21:59:42 2011 +0200
+++ b/src/ltpdarepo/templates/database.html	Fri Oct 14 22:02:41 2011 +0200
@@ -5,9 +5,9 @@
 <p class="discrete">{{ database.description }}</p>
 <ul class="actions">
   <li><a href="{{ url_for('browse.browse', database=database.id) }}">Browse</a></li>
-  {# <li><a href="{{ url_for('browse.activity', database=database.id) }}">Show activity</a></li> #}
   <li><a href="{{ url_for('browse.query', database=database.id) }}">Advanced search</a></li>
   <li><a href="{{ url_for('browse.timeseries', database=database.id) }}">Timeseries search</a></li>
+  <li><a href="{{ url_for('activity.activity', database=database.id) }}">Activity</a></li>
 </ul>
 <h2>Quick search</h2>
 <p class="discrete">Search objects by name:</p>
--- a/src/ltpdarepo/views/activity.py	Fri Oct 14 21:59:42 2011 +0200
+++ b/src/ltpdarepo/views/activity.py	Fri Oct 14 22:02:41 2011 +0200
@@ -1,6 +1,7 @@
-import datetime
+from datetime import datetime
+from dateutil.relativedelta import relativedelta, MO
 
-from flask import Blueprint, g, abort, render_template
+from flask import Blueprint, g, abort, render_template, request
 
 from ltpdarepo.database import Database
 from ltpdarepo.security import require, view
@@ -9,35 +10,39 @@
 
 
 @app.route('/<database>/activity')
-@app.route('/<database>/activity/<period>/<date>')
 @require('user')
-def activity(database, period='week', date=None):
+def activity(database, date=None):
     with view('database', database):
         db = Database().load(database)
         if db is None:
             # not found
             abort(404)
 
-        curs = g.db.cursor()
+        today = datetime.today().date()
+        date = request.args.get('date')
+        if date is not None:
+            today = datetime.strptime(date, '%Y-%m-%d').date()
 
-        if date is None:
-            today = datetime.date.today()
-        else:
-            today = datetime.datetime.strptime(date, '%Y-%m-%d').date()
-
-        activity = []
+        begin = today + relativedelta(day=1)
+        end = begin + relativedelta(months=1, days=-1)
+        prev = begin + relativedelta(months=-1)
+        next = begin + relativedelta(months=+1)
 
-        for i in range(0, 7):
-            start = today - datetime.timedelta(days=1 * i)
-            stop = today - datetime.timedelta(days=1 * (i - 1))
-            curs.execute("""SELECT COUNT(*) AS n
-                            FROM `%s`.objmeta
-                            WHERE submitted > %%s
-                            AND submitted < %%s""" % database, (start, stop))
-            n = curs.fetchone()[0]
-            activity.append((str(start), n))
+        curs = g.db.cursor()
+        
+        # prepare timeintervals table with proper intervals
+        curs.execute("""CALL makeintervals(%s, %s, 1, 'DAY')""", (begin, end))
 
-        return render_template('activity.html', database=db, activity=activity)
+        # collect number of objects for each interval
+        curs.execute("""SELECT ts.begin AS date, COUNT(objmeta.obj_id) AS count
+                        FROM ltpda.timeintervals AS ts
+                        LEFT OUTER JOIN `%s`.objmeta ON (objmeta.submitted BETWEEN ts.begin AND ts.end)
+                        GROUP BY ts.begin, ts.end""" % database)
+
+        activity = curs.fetchall()
+
+        return render_template('activity.html', database=db, activity=activity,
+                               curr=today, prev=prev, next=next, dt=relativedelta(days=1))
 
 
 module = app