Private
Public Access
1
0

list workouts for team members

This commit is contained in:
Sander Roosendaal
2017-02-14 10:50:03 +01:00
parent 9e737458b6
commit 253454ff3f
6 changed files with 181 additions and 115 deletions

View File

@@ -279,7 +279,7 @@ def handle_sendemail_request(email,name,code,teamname,requestor,id):
message += 'Click the direct link to accept: \n'
message += 'https://rowsandall.com/rowers/me/request/'+code+' \n\n'
message += 'Click the following link to reject the request: \n'
message += 'https://rowsandall.com/rowers/me/request/'+id+' \n\n'
message += 'https://rowsandall.com/rowers/me/request/'+str(id)+' \n\n'
message += 'You can find all pending requests on your team management page:\n'
message += 'https://rowsandall.com/rowers/me/teams\n\n'
message += "Best Regards, the Rowsandall Team"

View File

@@ -9,7 +9,8 @@
<div class="grid_12">
<h1>Forbidden</h1>
<p>
Access forbidden
Access forbidden. You probably tried to access functionality on a workout
or chart that is not owned by you.
</p>
</div>

View File

@@ -64,7 +64,11 @@
receive stroke
data from the site directly.</p>
<p>The REST API is a work in progress. </p>
<p>The REST API is a work in progress. We are open to improvement
suggestions (provided they don't break existing apps). Please send
email to <a href="mailto:info@rowsandall.com">info@rowsandall.com</a>
with questions and/or suggestions. We
will get back to you as soon as possible.</p>
<ul>
<li>Advantages

View File

@@ -10,7 +10,11 @@
Select start and end date for a date range:
<div class="grid_4 alpha">
{% if team %}
<form enctype="multipart/form-data" action="/rowers/list-workouts/team/{{ team.id }}/" method="post">
{% else %}
<form enctype="multipart/form-data" action="/rowers/list-workouts/" method="post">
{% endif %}
<table>
{{ dateform.as_table }}
@@ -24,7 +28,11 @@
</div>
<div class="grid_8 alpha">
{% if team %}
<h3>{{ team.name }} Team Workouts</h3>
{% else %}
<h3>My Workouts</h3>
{% endif %}
{% if workouts %}
<table width="100%" class="listtable">
@@ -38,8 +46,14 @@
<th> Duration </th>
<th> Avg HR </th>
<th> Max HR </th>
{% if not team %}
<th> Delete</th>
<th> Export</th>
{% else %}
<th colspan="2">
Owner
</th>
{% endif %}
</tr>
</thead>
<tbody>
@@ -47,19 +61,37 @@
<tr>
<td> {{ workout.date |truncatechars:15}} </td>
<td> {{ workout.starttime }} </td>
<td>
<td>
{% if workout.user.user == user %}
{% if workout.name != '' %}
<a href="/rowers/workout/{{ workout.id }}/edit">{{ workout.name }}</a> </td>
{% else %}
<a href="/rowers/workout/{{ workout.id }}/edit">No Name</a> </td>
{% endif %}
{% endif %}
{% else %}
{% if workout.name != '' %}
<a href="/rowers/workout/{{ workout.id }}/">{{ workout.name }}</a> </td>
{% else %}
<a href="/rowers/workout/{{ workout.id }}/">No Name</a> </td>
{% endif %}
{% endif %}
<td> {{ workout.workouttype }} </td>
<td> {{ workout.distance }}m</td>
<td> {{ workout.duration |durationprint:"%H:%M:%S.%f" }} </td>
<td> {{ workout.averagehr }} </td>
<td> {{ workout.maxhr }} </td>
<td> <a class="button red small" href="/rowers/workout/{{ workout.id }}/deleteconfirm">Delete</td>
<td> <a class="button blue small" href="/rowers/workout/{{ workout.id }}/export">Export</a> </td>
{% if not team %}
<td>
<a class="button red small" href="/rowers/workout/{{ workout.id }}/deleteconfirm">Delete
</td>
<td>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/export">Export</a>
</td>
{% else %}
<td colspan="2">
{{ workout.user.user.first_name }} {{ workout.user.user.last_name }}
</td>
{% endif %}
<td> <a class="button blue small" href="/rowers/workout/{{ workout.id }}/flexchart">Flex</a> </td>
@@ -106,8 +138,13 @@
<div class="grid_5 alpha">
{% if team %}
<form id="searchform" action="/rowers/list-workouts/team/{{ team.id }}/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}"
method="get" accept-charset="utf-8">
{% else %}
<form id="searchform" action="/rowers/list-workouts/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}"
method="get" accept-charset="utf-8">
{% endif %}
<div class="grid_3 prefix_1 alpha">
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search">
</div>

View File

@@ -109,6 +109,8 @@ urlpatterns = [
url(r'^list-workouts/c/(?P<message>\w+.*)/$',views.workouts_view),
url(r'^list-workouts/s/(?P<successmessage>\w+.*)/$',views.workouts_view),
url(r'^list-workouts/c/(?P<message>\w+.*)/s/(?P<successmessage>\w+.*)$',views.workouts_view),
url(r'^list-workouts/team/(?P<teamid>\d+)/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.workouts_view),
url(r'^list-workouts/team/(?P<teamid>\d+)/$',views.workouts_view),
url(r'^list-workouts/(?P<startdatestring>\w+.*)/(?P<enddatestring>\w+.*)$',views.workouts_view),
url(r'^list-workouts/$',views.workouts_view),
url(r'^list-graphs/$',views.graphs_view),

View File

@@ -14,6 +14,7 @@ from django.http import (
from django.contrib.auth import authenticate, login, logout
from rowers.forms import LoginForm,DocumentsForm,UploadOptionsForm
from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied
from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
@@ -1889,79 +1890,94 @@ def workout_recalcsummary_view(request,id=0):
def workouts_view(request,message='',successmessage='',
startdatestring="",enddatestring="",
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now()+datetime.timedelta(days=1)):
enddate=timezone.now()+datetime.timedelta(days=1),
teamid=0):
try:
r = Rower.objects.get(user=request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
startdate = dateform.cleaned_data['startdate']
enddate = dateform.cleaned_data['enddate']
else:
dateform = DateRangeForm(initial={
'startdate':startdate,
'enddate':enddate,
})
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
startdate = dateform.cleaned_data['startdate']
enddate = dateform.cleaned_data['enddate']
else:
dateform = DateRangeForm(initial={
'startdate':startdate,
'enddate':enddate,
})
startdate = datetime.datetime.combine(startdate,datetime.time())
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
enddate = enddate+datetime.timedelta(days=1)
if startdatestring:
startdate = iso8601.parse_date(startdatestring)
if enddatestring:
enddate = iso8601.parse_date(enddatestring)
startdate = datetime.datetime.combine(startdate,datetime.time())
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
enddate = enddate+datetime.timedelta(days=1)
if enddate < startdate:
s = enddate
enddate = startdate
startdate = s
workouts = Workout.objects.filter(user=r,
if startdatestring:
startdate = iso8601.parse_date(startdatestring)
if enddatestring:
enddate = iso8601.parse_date(enddatestring)
if enddate < startdate:
s = enddate
enddate = startdate
startdate = s
if teamid:
try:
theteam = Team.objects.get(id=teamid)
except Team.DoesNotExist:
raise Http404("Team doesn't exist")
workouts = Workout.objects.filter(team=theteam,
startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime")
query = request.GET.get('q')
if query:
query_list = query.split()
workouts = workouts.filter(
reduce(operator.and_,
(Q(name__icontains=q) for q in query_list)) |
reduce(operator.and_,
(Q(notes__icontains=q) for q in query_list))
)
paginator = Paginator(workouts,20) # show 25 workouts per page
page = request.GET.get('page')
try:
workouts = paginator.page(page)
except PageNotAnInteger:
workouts = paginator.page(1)
except EmptyPage:
workouts = paginator.page(paginator.num_pages)
today = timezone.now()
announcements = SiteAnnouncement.objects.filter(
expires__gte=today
).order_by(
"-created",
"-id"
)
return render(request, 'list_workouts.html',
{'workouts': workouts,
'message': message,
'successmessage':successmessage,
'dateform':dateform,
'startdate':startdate,
'enddate':enddate,
'announcements':announcements[0:4],
})
except Rower.DoesNotExist:
return HttpResponse("User has no rower instance")
else:
theteam = None
workouts = Workout.objects.filter(user=r,
startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime")
query = request.GET.get('q')
if query:
query_list = query.split()
workouts = workouts.filter(
reduce(operator.and_,
(Q(name__icontains=q) for q in query_list)) |
reduce(operator.and_,
(Q(notes__icontains=q) for q in query_list))
)
paginator = Paginator(workouts,20) # show 25 workouts per page
page = request.GET.get('page')
try:
workouts = paginator.page(page)
except PageNotAnInteger:
workouts = paginator.page(1)
except EmptyPage:
workouts = paginator.page(paginator.num_pages)
today = timezone.now()
announcements = SiteAnnouncement.objects.filter(
expires__gte=today
).order_by(
"-created",
"-id"
)
return render(request, 'list_workouts.html',
{'workouts': workouts,
'message': message,
'successmessage':successmessage,
'dateform':dateform,
'startdate':startdate,
'enddate':enddate,
'announcements':announcements[0:4],
'team':theteam,
})
# List of workouts to compare a selected workout to
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
@@ -2040,7 +2056,7 @@ def workout_comparison_list(request,id=0,message='',successmessage='',
'enddate':enddate,
})
except Rower.DoesNotExist:
return HttpResponse("User has no rower instance")
raise Http404("User has no rower instance")
# Basic 'EDIT' view of workout
def workout_view(request,id=0):
@@ -3384,7 +3400,7 @@ def workout_add_otw_powerplot_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3441,7 +3457,7 @@ def workout_add_piechart_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3499,7 +3515,7 @@ def workout_add_power_piechart_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3555,7 +3571,7 @@ def workout_add_timeplot_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3612,7 +3628,7 @@ def workout_add_distanceplot_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3667,7 +3683,7 @@ def workout_add_distanceplot2_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -3724,7 +3740,7 @@ def workout_add_timeplot2_view(request,id):
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,w)==False):
if (checkworkoutuser(request.user,w)==False):
raise PermissionDenied("You are not allowed add plots to this workout")
else:
f1 = w.csvfilename[6:-4]
@@ -4261,7 +4277,7 @@ def workout_delete_confirm_view(request, id=0):
def workout_delete_confirm_view(request, id=0):
try:
row = Workout.objects.get(id=id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to delete this workout")
else:
return render(request,'workout_delete_confirm.html',
@@ -4276,7 +4292,7 @@ def workout_delete_view(request,id=0):
def workout_delete_view(request,id=0):
try:
row = Workout.objects.get(id=id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to delete this workout")
else:
# files are removed by pre-delete in models.py
@@ -4297,7 +4313,7 @@ def graph_delete_confirm_view(request, id=0):
try:
img = GraphImage.objects.get(id=id)
row = Workout.objects.get(id=img.workout.id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to delete this workout")
else:
return render(request,'graphimage_delete_confirm.html',
@@ -4315,7 +4331,7 @@ def graph_delete_view(request,id=0):
try:
img = GraphImage.objects.get(id=id)
row = Workout.objects.get(id=img.workout.id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to delete this graph")
else:
img.delete()
@@ -4328,7 +4344,8 @@ def graph_delete_view(request,id=0):
return HttpResponseRedirect(url)
except GraphImage.DoesNotExist:
raise Http404("Graph Image doesn't exist")
raise Http404("Graph Image doesn't exist")
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
# A page with all the recent graphs (searchable on workout name)
@@ -4355,7 +4372,7 @@ def graphs_view(request):
return render(request, 'list_graphs.html',
{'graphs1': g[0:5],
'graphs2': g[5:10]})
except Rower.DoesNotExist:
except Rower.DoesNotExist:
raise Http404("User has no rower instance")
# Show the chart (png image)
@@ -4380,7 +4397,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
def workout_summary_restore_view(request,id,message="",successmessage=""):
try:
row = Workout.objects.get(id=id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to edit this workout")
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
@@ -4400,7 +4417,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
hrtr=r.tr,hran=r.an,ftp=r.ftp,
powerperc=powerperc,powerzones=r.powerzones)
rowdata = rdata(f1,rower=rr)
if rowdata == 0:
if rowdata == 0:
raise Http404("Error: CSV Data File Not Found")
rowdata.restoreintervaldata()
rowdata.write_csv(f1,gzip=True)
@@ -4435,7 +4452,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
):
try:
row = Workout.objects.get(id=id)
if (checkworkoutuser(request.user,row)==False):
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("You are not allowed to edit this workout")
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
@@ -4926,30 +4943,33 @@ def rower_edit_view(request,message=""):
'grants':grants,
'rower':r,
})
except Rower.DoesNotExist:
except Rower.DoesNotExist:
raise Http404("This user doesn't exist")
# Revoke an app that you granted access through the API.
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@login_required()
def rower_revokeapp_view(request,id=0):
tokens = AccessToken.objects.filter(user=request.user,application=id)
refreshtokens = AccessToken.objects.filter(user=request.user,application=id)
for token in tokens:
token.revoke()
for token in refreshtokens:
def rower_revokeapp_view(request,id=0):
try:
tokens = AccessToken.objects.filter(user=request.user,application=id)
refreshtokens = AccessToken.objects.filter(user=request.user,application=id)
for token in tokens:
token.revoke()
for token in refreshtokens:
token.revoke()
r = Rower.objects.get(user=request.user)
form = RowerForm(instance=r)
powerform = RowerPowerForm(instance=r)
grants = AccessToken.objects.filter(user=request.user)
return render(request, 'rower_form.html',
{
'form':form,
'powerform':powerform,
'grants':grants,
r = Rower.objects.get(user=request.user)
form = RowerForm(instance=r)
powerform = RowerPowerForm(instance=r)
grants = AccessToken.objects.filter(user=request.user)
return render(request, 'rower_form.html',
{
'form':form,
'powerform':powerform,
'grants':grants,
})
except AccessToken.DoesNotExist:
raise Http404("Access token doesn't exist")
@@ -5130,13 +5150,11 @@ def team_view(request,id=0,message='',successmessage=''):
ismember = 0
hasrequested = 0
r = Rower.objects.get(user=request.user)
myteams = Team.objects.filter(manager=request.user)
myteams = Team.objects.filter(manager=request.user)
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist:
raise Http404("Team doesn't exist")
@@ -5187,7 +5205,7 @@ def team_leaveconfirm_view(request,id=0):
def team_leaveconfirm_view(request,id=0):
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist:
raise Http404("Team doesn't exist")
return render(request,'teamleaveconfirm.html',
@@ -5297,7 +5315,11 @@ def manager_requests_view(request,code=None,message='',successmessage=''):
@login_required()
def team_requestmembership_view(request,teamid,userid):
def team_requestmembership_view(request,teamid,userid):
try:
t = Team.objects.get(id=teamid)
except Team.DoesNotExist:
raise Http404("Team doesn't exist")
res,text = teams.create_request(t,userid)
if res:
@@ -5397,7 +5419,7 @@ def team_edit_view(request,id=0):
def team_edit_view(request,id=0):
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist:
raise Http404("Team does not exist")
if request.method == 'POST':
@@ -5464,9 +5486,9 @@ def team_deleteconfirm_view(request,id):
r = Rower.objects.get(user=request.user)
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist:
raise Http404("This team doesn't exist")
if t.manager != request.user:
if t.manager != request.user:
raise PermissionDenied("You are not allowed to delete this team")
return render(request,'teamdeleteconfirm.html',
@@ -5479,9 +5501,9 @@ def team_delete_view(request,id):
r = Rower.objects.get(user=request.user)
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist:
raise Http404("This team doesn't exist")
if t.manager != request.user:
if t.manager != request.user:
raise PermissionDenied("You are not allowed to delete this team")
teams.remove_team(t.id)