Private
Public Access
1
0

Merge branch 'feature/multicompare3' into develop

This commit is contained in:
Sander Roosendaal
2017-02-23 15:31:46 +01:00
8 changed files with 177 additions and 61 deletions

View File

@@ -19,7 +19,7 @@ from bokeh.layouts import layout,widgetbox
from bokeh.layouts import row as layoutrow
from bokeh.layouts import column as layoutcolumn
from bokeh.models import LinearAxis,LogAxis,Range1d,DatetimeTickFormatter,HoverTool
from bokeh.io import output_file, show
from bokeh.io import output_file, show, vplot
from bokeh.models import (
GMapPlot, GMapOptions, ColumnDataSource, Circle,
DataRange1d, PanTool, WheelZoomTool, BoxSelectTool,
@@ -1604,10 +1604,6 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
if datadf.empty:
return ['','<p>No non-zero data in selection</p>','','']
if xparam != 'distance' and xparam != 'time' and xparam != 'cumdist':
xaxmax = yaxmaxima[xparam]
xaxmin = yaxminima[xparam]
@@ -1673,17 +1669,29 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
group
)
TIPS = OrderedDict([
('time','@ftime'),
('pace','@fpace'),
('hr','@hr'),
('spm','@spm{1.1}'),
('distance','@distance{5}'),
])
hover = plot.select(type=HoverTool)
hover.tooltips = TIPS
if labeldict:
legend=labeldict[id]
else:
legend=str(id)
if plottype=='line':
plot.line('x','y',source=source,color=color,legend=legend)
l1 = plot.line('x','y',source=source,color=color,legend=legend)
else:
plot.scatter('x','y',source=source,color=color,legend=legend,
l1 = plot.scatter('x','y',source=source,color=color,legend=legend,
fill_alpha=0.4,line_color=None)
plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS))
cntr += 1
plot.legend.location='bottom_right'
@@ -1725,7 +1733,7 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
promember=0,plottype='line'):
promember=0,plottype='line'):
@@ -1743,8 +1751,8 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
rowdata2 = dataprep.getsmallrowdata_db(columns,ids=[id2])
row1 = Workout.objects.get(id=id1)
row2 = Workout.objects.get(id=id2)
if rowdata1.empty:
return "","CSV Data File Not Found"
else:
@@ -1797,32 +1805,39 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
data = pd.DataFrame(
data1 = pd.DataFrame(
dict(
x1=x1,
x2=x2,
y1=y1,
y2=y2,
ftime1=ftime1,
ftime2=ftime2,
fpace1=fpace1,
fpace2=fpace2,
hr1 = hr1,
hr2 = hr2,
spm1 = spm1,
spm2 = spm2,
distance1=distance1,
)
).dropna()
data2 = pd.DataFrame(
dict(
x2=x2,
y2=y2,
ftime2=ftime2,
fpace2=fpace2,
hr2 = hr2,
spm2 = spm2,
distance2=distance2,
)
).dropna()
source = ColumnDataSource(
data
source1 = ColumnDataSource(
data1
)
source2 = ColumnDataSource(
data2
)
# create interactive plot
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
@@ -1830,22 +1845,52 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
plot_width=920,
toolbar_sticky=False)
TIPS = OrderedDict([
('time','@ftime1'),
('pace','@fpace1'),
('hr','@hr1'),
('spm','@spm1{1.1}'),
('distance','@distance1{5}'),
])
TIPS2 = OrderedDict([
('time','@ftime2'),
('pace','@fpace2'),
('hr','@hr2'),
('spm','@spm2{1.1}'),
('distance','@distance2{5}'),
])
hover1 = plot.select(type=HoverTool)
hover1.tooltips = TIPS
hover2 = plot.select(type=HoverTool)
hover2.tooltips = TIPS2
if plottype=='line':
plot.line('x1','y1',source=source,color="blue",legend=row1.name)
plot.line('x2','y2',source=source,color="red",legend=row2.name)
l1 = plot.line('x1','y1',source=source1,
color="blue",legend=row1.name,
)
l2 = plot.line('x2','y2',source=source2,
color="red",legend=row2.name,
)
elif plottype=='scatter':
plot.scatter('x1','y1',source=source,legend=row1.name,fill_alpha=0.4,
line_color=None)
plot.scatter('x2','y2',source=source,legend=row2.name,fill_alpha=0.4,
line_color=None,color="red")
l1 = plot.scatter('x1','y1',source=source1,legend=row1.name,
fill_alpha=0.4,
line_color=None)
l2 = plot.scatter('x2','y2',source=source2,legend=row2.name,
fill_alpha=0.4,
line_color=None,color="red")
plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS))
plot.add_tools(HoverTool(renderers=[l2],tooltips=TIPS2))
plot.legend.location = "bottom_right"
plot.title.text = row1.name+' vs '+row2.name
plot.title.text_font_size=value("1.2em")
plot.xaxis.axis_label = axlabels[xparam]
plot.yaxis.axis_label = axlabels[yparam]
if xparam == 'time':
plot.xaxis[0].formatter = DatetimeTickFormatter(
@@ -1863,27 +1908,10 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
seconds = ["%S"],
minutes = ["%M"]
)
plot.y_range = Range1d(ymin,ymax)
#plot.y_range = Range1d(ymin,ymax)
hover = plot.select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
('time1','@ftime1'),
('time2','@ftime2'),
('pace1','@fpace1'),
('pace2','@fpace2'),
('hr1','@hr1'),
('hr2','@hr2'),
('spm1','@spm1{1.1}'),
('spm2','@spm2{1.1}'),
('distance1','@distance1{5}'),
('distance2','@distance2{5}'),
])
hover.mode = 'mouse'
script, div = components(plot)
return [script,div]

View File

@@ -891,6 +891,7 @@ class WorkoutComment(models.Model):
comment = models.TextField(max_length=300)
created = models.DateTimeField(default=timezone.now)
read = models.BooleanField(default=False)
notification = models.BooleanField(default=False,verbose_name="Send me notifications")
user = models.ForeignKey(User)
workout = models.ForeignKey(Workout)
@@ -905,7 +906,7 @@ class WorkoutComment(models.Model):
class WorkoutCommentForm(ModelForm):
class Meta:
model = WorkoutComment
fields = ['comment',]
fields = ['comment','notification']
widgets = {
'comment': forms.Textarea,
}

View File

@@ -273,6 +273,37 @@ def handle_sendemail_invite(email,name,code,teamname,manager):
return 1
@app.task
def handle_sendemailnewresponse(first_name,last_name,
email,
commenter_first_name,
commenter_last_name,
comment,
workoutname,workoutid,commentid):
fullemail = first_name+' '+last_name+' <'+email+'>'
subject = 'New comment on workout '+workoutname
message = 'Dear '+first_name+',\n\n'
message += commenter_first_name+' '+commenter_last_name
message += ' has written a new comment on the workout '
message += workoutname+'\n\n'
message += comment
message += '\n\n'
message += 'You can read the comment here:\n'
message += 'https://rowsandall.com/rowers/workout/'+str(workoutid)+'/comment'
message += '\n\n'
message += 'You are receiving this email because you are subscribed '
message += 'to comments on this workout. To unsubscribe, follow this link:\n'
message += 'https://rowsandall.com/rowers/workout/unsubscribe/'+str(workoutid)+'/'
email = EmailMessage(subject, message,
'Rowsandall <info@rowsandall.com>',
[fullemail])
res = email.send()
return 1
@app.task
def handle_sendemailnewcomment(first_name,
last_name,

View File

@@ -9,7 +9,7 @@
<div class="grid_12">
<div class="grid_8 suffix_4">
{% include "teambuttons.html" with teamid=teamid%}
{% include "teambuttons.html" with teamid=team.id %}
</div>
</div>
<div class="grid_12 alpha">

View File

@@ -57,7 +57,7 @@
{% endfor %}
<div id="form" class="grid_6 alpha">
<form enctype="multipart/form-data" action="" method="post">
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/comment" method="post">
<table width=100%>
{{ form.as_table }}
</table>

View File

@@ -151,6 +151,7 @@ urlpatterns = [
url(r'^workout/upload/(.+.*)$',views.workout_upload_view),
url(r'^workout/(?P<id>\d+)/histo$',views.workout_histo_view),
url(r'^workout/(?P<id>\d+)/forcecurve$',views.workout_forcecurve_view),
url(r'^workout/(?P<id>\d+)/unsubscribe$',views.workout_unsubscribe_view),
url(r'^workout/(?P<id>\d+)/export/c/(?P<message>\w+.*)/s/(?P<successmessage>\w+.*)$',views.workout_export_view),
url(r'^workout/(?P<id>\d+)/export/c/(?P<message>\w+.*)$',views.workout_export_view),
url(r'^workout/(?P<id>\d+)/export/s/(?P<successmessage>\w+.*)$',views.workout_export_view),

View File

@@ -60,7 +60,8 @@ from rest_framework.parsers import JSONParser
from rowers.rows import handle_uploaded_file
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
from rowers.tasks import (
handle_sendemail_unrecognized,handle_sendemailnewcomment
handle_sendemail_unrecognized,handle_sendemailnewcomment,
handle_sendemailnewresponse,
)
from scipy.signal import savgol_filter
@@ -2064,10 +2065,6 @@ def multi_compare_view(request):
if result:
promember=1
if 'ids' in request.session:
print request.session['ids']
print request.POST
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
@@ -3586,6 +3583,37 @@ def workout_export_view(request,id=0, message="", successmessage=""):
'successmessage':successmessage,
'c2userid':c2userid,
})
#
@login_required()
def workout_unsubscribe_view(request,id=0):
try:
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if w.privacy == 'private' and w.user.user != request.user:
return HttpResponseForbidden("Permission error")
comments = WorkoutComment.objects.filter(workout=w,
user=request.user).order_by("created")
for c in comments:
c.notify = False
c.save()
form = WorkoutCommentForm()
message = 'You have been unsubscribed from new comment notifications for this workout'
return render(request,
'workout_comments.html',
{'workout':w,
'comments':comments,
'successmessage':message,
'form':form,
})
# list of comments to a workout
@login_required()
@@ -3597,6 +3625,8 @@ def workout_comment_view(request,id=0):
if w.privacy == 'private' and w.user.user != request.user:
return HttpResponseForbidden("Permission error")
comments = WorkoutComment.objects.filter(workout=w).order_by("created")
# ok we're permitted
if request.method == 'POST':
@@ -3604,7 +3634,9 @@ def workout_comment_view(request,id=0):
form = WorkoutCommentForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
comment = cd['comment']
comment = cd['comment']
notification = cd['notification']
c = WorkoutComment(workout=w,user=request.user,comment=comment,
notification=notification)
c.save()
if settings.DEBUG:
@@ -3615,6 +3647,7 @@ def workout_comment_view(request,id=0):
request.user.last_name,
comment,w.name,
w.id)
elif request.user != r.user:
res = queuehigh.enqueue(handle_sendemailnewcomment,r.user.first_name,
@@ -3622,9 +3655,30 @@ def workout_comment_view(request,id=0):
r.user.email,
request.user.first_name,
request.user.last_name,
comment,w.name,w.id)
comment,w.name,w.id)
commenters = {oc.user for oc in comments if oc.notification}
for u in commenters:
if settings.DEBUG:
res = handle_sendemailnewresponse.delay(u.first_name,
u.last_name,
u.email,
request.user.first_name,
request.user.last_name,
comment,
w.name,
w.id,
c.id)
else:
res = queuelow.enqueue(handle_sendemailnewresponse,
u.first_name,
u.last_name,
u.email,
request.user.first_name,
request.user.last_name,
comment,
w.name,
w.id,
c.id)
form = WorkoutCommentForm()

View File

@@ -799,9 +799,10 @@ a.wh:hover {
/* talk bubble contents */
.talktext{
padding: 1em;
text-align: left;
line-height: 1.5em;
padding: 1em;
text-align: left;
line-height: 1.5em;
word-wrap: break-word;
}
.talktext p{
/* remove webkit p margins */