Skip to content

Commit

Permalink
add merging and bugfixes
Browse files Browse the repository at this point in the history
add merging of sessions if the connection got lost more then timeout minutes.
add deleting links into admin
some bugfixes
  • Loading branch information
poelzi committed Jul 12, 2010
1 parent d191ec2 commit d4f2be6
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 26 deletions.
7 changes: 7 additions & 0 deletions db/admin.py
@@ -0,0 +1,7 @@
from django.contrib import admin
from uberclock.db.models import *


admin.site.register(Detector)
admin.site.register(WakeupTime)
admin.site.register(Session)
29 changes: 29 additions & 0 deletions db/models.py
@@ -1,7 +1,9 @@
from django.db import models
from uberclock.tools import ez_chronos
from django.contrib.auth.models import User
from django.contrib import admin
from django.conf import settings
from django.utils.dateformat import time_format
import struct
import logging
import datetime
Expand Down Expand Up @@ -105,6 +107,30 @@ def week(self):
def __repr__(self):
return "<Session %s %s-%s>" %(self.user, self.start, self.stop)

def __str__(self):
return "Session %s %s-%s" %(self.user, self.start, self.stop)

def merge(self, source):
source.entry_set.all().update(session=self)
source.learndata_set.all().delete()

def cifn(key):
var = getattr(source, key)
if var and not getattr(self, key):
setattr(self, key, var)
# copy usefull variables
for key in ["user", "wakeup", "rating"]:
cifn(key)

if self.entry_set.all().count():
self.start = self.entry_set.all().order_by('date')[0].date
self.stop = self.entry_set.all().order_by('-date')[0].date

self.save()
source.delete()



@property
def length(self):
s = (self.stop - self.start).seconds
Expand All @@ -122,6 +148,9 @@ class Entry(models.Model):
def __repr__(self):
return "<Entry %s %d>" %(self.date, self.value)

def __unicode__(self):
return u"Entry at %s: %s" %(self.date, time_format(self.date, settings.TIME_FORMAT))


class LearnData(models.Model):
"""
Expand Down
3 changes: 2 additions & 1 deletion settings.py
Expand Up @@ -82,6 +82,7 @@
'piston.middleware.ConditionalMiddlewareCompatProxy',
'piston.middleware.CommonMiddlewareCompatProxy',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
Expand All @@ -102,7 +103,7 @@
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.markup',
# 'django.contrib.messages',
'django.contrib.messages',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
'uberclock.db',
Expand Down
34 changes: 25 additions & 9 deletions templates/base.html
Expand Up @@ -15,7 +15,7 @@
text-align: center;
list-style-type: none;
}
div.top {
div.menu {
display: block;
}
body {
Expand All @@ -35,6 +35,14 @@
color: white;
}

#moreactions_box {
border: 1px solid lightBlue;
}

li {
text-align: left;

}

</style>

Expand All @@ -46,15 +54,23 @@
{% block header_extra %}{% endblock %}

</head><body>
<div class="top">
<ul class="topmenu">
<li class="toplink"><a href="/">Home</a></li>
<li class="toplink"><a href="/set/">Set</a></li>
<li class="toplink"><a href="/stats/">Stats</a></li>
{% block menuextra %}{% endblock %}
</ul>
<div class="menu">
<ul class="topmenu">
<li class="toplink"><a href="/">Home</a></li>
<li class="toplink"><a href="/set/">Set</a></li>
<li class="toplink"><a href="/stats/">Stats</a></li>
{% block menuextra %}{% endblock %}
</ul>
</div>
<br/><br/>
<br/>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<br/>
<div id="maindiv">
{% block content %}{% endblock %}
</div>
Expand Down
53 changes: 53 additions & 0 deletions webclock/decorators.py
@@ -0,0 +1,53 @@
try:
from functools import wraps
except ImportError:
from django.utils.functional import wraps

from django.shortcuts import render_to_response
from django.template import RequestContext

def confirm_required(template_name, context_creator, key='__confirm__'):
"""
Decorator for views that need confirmation page. For example, delete
object view. Decorated view renders confirmation page defined by template
'template_name'. If request.POST contains confirmation key, defined
by 'key' parameter, then original view is executed.
Context for confirmation page is created by function 'context_creator',
which accepts same arguments as decorated view.
Example
-------
def remove_file_context(request, id):
file = get_object_or_404(Attachment, id=id)
return RequestContext(request, {'file': file})
@confirm_required('remove_file_confirm.html', remove_file_context)
def remove_file_view(request, id):
file = get_object_or_404(Attachment, id=id)
file.delete()
next_url = request.GET.get('next', '/')
return HttpResponseRedirect(next_url)
Example of HTML template
------------------------
<h1>Remove file {{ file }}?</h1>
<form method="POST" action="">
<input type="hidden" name="__confirm__" value="1" />
<input type="submit" value="delete"/> <a href="{{ file.get_absolute_url }}">cancel</a>
</form>
"""
def decorator(func):
def inner(request, *args, **kwargs):
if request.POST.has_key(key):
return func(request, *args, **kwargs)
else:
context = context_creator and context_creator(request, *args, **kwargs) \
or RequestContext(request)
return render_to_response(template_name, context)
return wraps(func)(inner)
return decorator
16 changes: 15 additions & 1 deletion webclock/templates/stats_detail_js.html
Expand Up @@ -27,6 +27,20 @@
<td style="text-align:center">
<div class="jqPlot" id="chart2" style="height:120px; width:180px;"></div>
<button onclick="controllerPlot1.resetZoom()">Reset Zoom</button><br/><br/><br/>
<div id="moreactions_box">
<div id="moreactions_toggler"><a id="moreactions_toggle" href="">More Actions</a></div>
<div id="moreactions">
<ul>
<li><a href="{% url admin:db_session_delete session.id %}">Delete</a></li>
{% if prev %}
<li><a href="{% url stats_merge session.id prev.id %}">Merge with Previous</a></li>
{% endif %}
{% if next %}
<li><a href="{% url stats_merge session.id next.id %}">Merge with Next</a></li>
{% endif %}
</ul>
</div>
</div>
<p>Select type to edit:<br/>
<select id="selectType">
<option value="wake">Wakeup</option>
Expand Down Expand Up @@ -152,7 +166,7 @@
function plot() {
//global plot1, plot2;
plot1 = $.jqplot('chart1', [Points, Extra[0], Extra[1], Extra[2], Extra[3]], {
title:'{{ session.start|date }} - {{ session.stop|date }}',
title:'{{ session.start|date:"DATE_FORMAT" }}: {{ session.start|time }} - {{ session.stop|time }}',
axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer,
tickOptions:{formatString:'%H:%M:%S',
angle: -30},
Expand Down
13 changes: 13 additions & 0 deletions webclock/templates/webclock/confirm_merge.html
@@ -0,0 +1,13 @@
{% extends "base.html" %}


{% block content %}
<h1>Are you sure ?</h1>
You will merge session {{ source.id }} into {{ session.id }}.
This will destroy all aditional data known from the source session.

<form method="POST" action="{% url stats_merge session.id source.id %}">
<input type="hidden" name="__confirm__" value="1" />{% csrf_token %}
<input type="submit" value="merge"/> <a href="{{ session.get_absolute_url }}">cancel</a>
</form>
{% endblock %}
4 changes: 3 additions & 1 deletion webclock/urls.py
Expand Up @@ -6,6 +6,8 @@
(r'^$', views.index),
(r'^stats/png_graph/(?P<session>\d+)/', views.png_graph),
(r'^stats/png_graph/', views.png_graph),
(r'^stats/(\d+)/', views.stats_detail),
url(r'^stats/merge/(?P<session>\d+)/(?P<source>\d+)/', views.stats_merge, name="stats_merge"),
url(r'^stats/delete/(?P<session>\d+)/', views.stats_delete, name="stats_delete"),
url(r'^stats/(\d+)/', views.stats_detail, name="stats"),
(r'^stats/', views.stats),
)
55 changes: 41 additions & 14 deletions webclock/views.py
Expand Up @@ -2,12 +2,19 @@
# Create your views here.
import datetime, os, re


from django.utils.translation import gettext as _
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.http import HttpResponse
from django.http import HttpResponse, HttpResponseRedirect
from django.conf import settings
from django.contrib import messages
from django.core.urlresolvers import reverse


from django.utils.translation import gettext as _

from uberclock.db.models import Entry, Session
from uberclock.webclock.decorators import confirm_required

INDEX_PATH = os.path.join(os.path.dirname(__file__),
"templates", "webclock", "index")
Expand Down Expand Up @@ -87,16 +94,14 @@ def stats_detail(request, session):
now = datetime.datetime.now()
sess = get_object_or_404(Session, id__exact=session)

next = Session.objects.filter(id__exact=sess.id+1)
if next:
next = next[0]
else:
try:
next = Session.objects.filter(id__gt=sess.id)[0]
except IndexError:
next = None

prev = Session.objects.filter(id__exact=sess.id-1)
if prev:
prev = prev[0]
else:
try:
prev = Session.objects.filter(id__lt=sess.id).order_by('-id')[0]
except IndexError:
prev = None

typ = request.COOKIES.get("webclock_stats", "png")
Expand Down Expand Up @@ -129,13 +134,35 @@ def stats_detail(request, session):
return ret


def merge_session_context(request, session, source):
session = get_object_or_404(Session, id=session)
source = get_object_or_404(Session, id=source)
return RequestContext(request, {'session': session, 'source': source})

@confirm_required('webclock/confirm_merge.html', merge_session_context)
def stats_merge(request, session, source):

sess = get_object_or_404(Session, id__exact=session)
sess.merge(Session.objects.get(id__exact=source))

messages.add_message(request, messages.INFO, _("Successfull merged"))

return HttpResponseRedirect(reverse("stats", args=(session,)))

def stats_delete(request, session):
pass



# file charts.py
def png_graph(request, session=None):
import random
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import DateFormatter

try:
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import DateFormatter
except:
return HttpResponse("Install matplotlib to see graphics", status=500)

fig=Figure()
ax=fig.add_subplot(111)
Expand Down

0 comments on commit d4f2be6

Please sign in to comment.