team manager can upload on behalf of team member
This commit is contained in:
@@ -90,6 +90,24 @@ class UploadOptionsForm(forms.Form):
|
|||||||
class Meta:
|
class Meta:
|
||||||
fields = ['make_plot','plottype','upload_toc2','makeprivate']
|
fields = ['make_plot','plottype','upload_toc2','makeprivate']
|
||||||
|
|
||||||
|
# The form to indicate additional actions to be performed immediately
|
||||||
|
# after a successful upload. This version allows the Team manager to select
|
||||||
|
# a team member
|
||||||
|
class TeamUploadOptionsForm(forms.Form):
|
||||||
|
plotchoices = (
|
||||||
|
('timeplot','Time Plot'),
|
||||||
|
('distanceplot','Distance Plot'),
|
||||||
|
('pieplot','Pie Chart'),
|
||||||
|
)
|
||||||
|
make_plot = forms.BooleanField(initial=False,required=False)
|
||||||
|
plottype = forms.ChoiceField(required=False,
|
||||||
|
choices=plotchoices,
|
||||||
|
initial='timeplot',
|
||||||
|
label='Plot Type')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
fields = ['make_plot','plottype']
|
||||||
|
|
||||||
# This form is used on the Analysis page to add a custom distance/time
|
# This form is used on the Analysis page to add a custom distance/time
|
||||||
# trial and predict the pace
|
# trial and predict the pace
|
||||||
class PredictedPieceForm(forms.Form):
|
class PredictedPieceForm(forms.Form):
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{% load cookielaw_tags %}
|
{% load cookielaw_tags %}
|
||||||
{% load analytical %}
|
{% load analytical %}
|
||||||
|
{% load rowerfilters %}
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -143,14 +144,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_1 tooltip">
|
<div class="grid_1 tooltip">
|
||||||
{% if user.is_authenticated and teams %}
|
{% if user.is_authenticated and user|has_teams %}
|
||||||
<div class="grid_1 alpha dropdown">
|
<div class="grid_1 alpha dropdown">
|
||||||
<button class="grid_1 alpha button gray small dropbtn">
|
<button class="grid_1 alpha button gray small dropbtn">
|
||||||
Teams
|
Teams
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<a class="button gray small" href="/rowers/me/teams/">Manage Teams</a>
|
<a class="button gray small" href="/rowers/me/teams/">Manage Teams</a>
|
||||||
{% for t in teams %}
|
{% if user|is_manager %}
|
||||||
|
<a class="button gray small" href="/rowers/workout/upload/team/">Upload Team Member Workout</a>
|
||||||
|
{% endif %}
|
||||||
|
{% for t in user|user_teams %}
|
||||||
<a class="button gray small" href="/rowers/list-workouts/team/{{ t.id }}/">{{ t.name }}</a>
|
<a class="button gray small" href="/rowers/list-workouts/team/{{ t.id }}/">{{ t.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{% load cookielaw_tags %}
|
{% load cookielaw_tags %}
|
||||||
{% load analytical %}
|
{% load analytical %}
|
||||||
|
{% load rowerfilters %}
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -162,13 +163,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_1 tooltip">
|
<div class="grid_1 tooltip">
|
||||||
{% if user.is_authenticated and teams %}
|
{% if user.is_authenticated and user|user_teams %}
|
||||||
<div class="grid_1 alpha dropdown">
|
<div class="grid_1 alpha dropdown">
|
||||||
<button class="grid_1 alpha button gray small dropbtn">
|
<button class="grid_1 alpha button gray small dropbtn">
|
||||||
Teams
|
Teams
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
{% for t in teams %}
|
<a class="button gray small" href="/rowers/me/teams/">Manage Teams</a>
|
||||||
|
{% if user|is_manager %}
|
||||||
|
<a class="button gray small" href="/rowers/workout/upload/team/">Upload Team Member Workout</a>
|
||||||
|
{% endif %}
|
||||||
|
{% for t in user|user_teams %}
|
||||||
<a class="button gray small" href="/rowers/list-workouts/team/{{ t.id }}/">{{ t.name }}</a>
|
<a class="button gray small" href="/rowers/list-workouts/team/{{ t.id }}/">{{ t.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load staticfiles %}
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
{% block title %}File loading{% endblock %}
|
{% block title %}File loading{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
|
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
|
||||||
<div id="left" class="grid_6 alpha">
|
<div id="left" class="grid_6 alpha">
|
||||||
<h1>Upload Workout File</h1>
|
<h1>Upload Workout File</h1>
|
||||||
|
{% if user.is_authenticated and user|is_manager %}
|
||||||
|
<p>Looking for <a href="/rowers/workout/upload/team/">Team Manager
|
||||||
|
Upload?</a></p>
|
||||||
|
{% endif %}
|
||||||
{% if form.errors %}
|
{% if form.errors %}
|
||||||
<p style="color: red;">
|
<p style="color: red;">
|
||||||
Please correct the error{{ form.errors|pluralize }} below.
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
|
|||||||
@@ -35,7 +35,9 @@
|
|||||||
|
|
||||||
<div id="workouts_table" class="grid_8 alpha">
|
<div id="workouts_table" class="grid_8 alpha">
|
||||||
{% if team %}
|
{% if team %}
|
||||||
{% include "teambuttons.html" with teamid=team.id %}
|
<div class="grid_8 alpha">
|
||||||
|
{% include "teambuttons.html" with teamid=team.id %}
|
||||||
|
</div>
|
||||||
<h3>{{ team.name }} Team Workouts</h3>
|
<h3>{{ team.name }} Team Workouts</h3>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h3>My Workouts</h3>
|
<h3>My Workouts</h3>
|
||||||
|
|||||||
55
rowers/templates/team_document_form.html
Normal file
55
rowers/templates/team_document_form.html
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block title %}File loading{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
|
||||||
|
<div id="left" class="grid_6 alpha">
|
||||||
|
<h1>Upload Workout File</h1>
|
||||||
|
{% if form.errors %}
|
||||||
|
<p style="color: red;">
|
||||||
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{{ rowerform.as_table }}
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
||||||
|
<input class="button green" type="submit" value="Submit">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="right" class="grid_6 omega">
|
||||||
|
<h1>Optional extra actions</h1>
|
||||||
|
<p>
|
||||||
|
<table>
|
||||||
|
{{ optionsform.as_table }}
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You can select one static plot to be generated immediately for this workout. You can select to upload to Concept2 automatically. If you check "make private", this workout will not be visible to your followers and will not show up in your teams' workouts list.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Valid file types are:
|
||||||
|
<ul>
|
||||||
|
<li>Painsled iOS Stroke Export (CSV)</li>
|
||||||
|
<li>Painsled desktop version Stroke Export (CSV)</li>
|
||||||
|
<li>A TCX file with location data (lat,long) - with or without Heart Rate value, for example from RiM or CrewNerd</li>
|
||||||
|
<li>RowPro CSV export</li>
|
||||||
|
<li>SpeedCoach GPS and SpeedCoach GPS 2 CSV export</li>
|
||||||
|
<li>ErgData CSV export</li>
|
||||||
|
<li>ErgStick CSV export</li>
|
||||||
|
<li>BoatCoach CSV export</li>
|
||||||
|
<li>A FIT file with location data (experimental)</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
{% load rowerfilters %}
|
||||||
<div class="grid_2 alpha">
|
<div class="grid_2 alpha">
|
||||||
<p>
|
<p>
|
||||||
<a class="button gray small" href="/rowers/list-workouts/team/{{ teamid }}/">Team Workouts</a>
|
<a class="button gray small" href="/rowers/list-workouts/team/{{ teamid }}/">Team Workouts</a>
|
||||||
@@ -8,8 +9,17 @@
|
|||||||
<a class="button gray small" href="/rowers/team-compare-select/team/{{ teamid }}/">Multi Compare</a>
|
<a class="button gray small" href="/rowers/team-compare-select/team/{{ teamid }}/">Multi Compare</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2 suffix_2 omega">
|
<div class="grid_2">
|
||||||
<p>
|
<p>
|
||||||
<a class="button gray small" href="/rowers/team/{{ teamid }}/">Team Page</a>
|
<a class="button gray small" href="/rowers/team/{{ teamid }}/">Team Page</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid_2 omega">
|
||||||
|
{% if user|is_manager and user|has_teams %}
|
||||||
|
<p>
|
||||||
|
<a class="button gray small" href="/rowers/workout/upload/team/">Upload Workout</a>
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p> </p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -65,3 +65,35 @@ def times(number):
|
|||||||
def get_field_id(id,s,form):
|
def get_field_id(id,s,form):
|
||||||
field_name = s+str(id)
|
field_name = s+str(id)
|
||||||
return form.__getitem__(field_name)
|
return form.__getitem__(field_name)
|
||||||
|
|
||||||
|
from rowers.models import Rower,Team
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def is_manager(user):
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
return r.rowerplan == 'coach'
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def user_teams(user):
|
||||||
|
try:
|
||||||
|
therower = Rower.objects.get(user=user)
|
||||||
|
teams1 = therower.team.all()
|
||||||
|
teams2 = Team.objects.filter(manager=user)
|
||||||
|
teams = list(set(teams1).union(set(teams2)))
|
||||||
|
except TypeError:
|
||||||
|
teams = []
|
||||||
|
|
||||||
|
return teams
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def has_teams(user):
|
||||||
|
try:
|
||||||
|
therower = Rower.objects.get(user=user)
|
||||||
|
teams1 = therower.team.all()
|
||||||
|
teams2 = Team.objects.filter(manager=user)
|
||||||
|
teams = list(set(teams1).union(set(teams2)))
|
||||||
|
return True
|
||||||
|
except TypeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return False
|
||||||
|
|||||||
@@ -157,8 +157,12 @@ urlpatterns = [
|
|||||||
url(r'^graph/(\d+)/$',views.graph_show_view),
|
url(r'^graph/(\d+)/$',views.graph_show_view),
|
||||||
url(r'^graph/(\d+)/deleteconfirm$',views.graph_delete_confirm_view),
|
url(r'^graph/(\d+)/deleteconfirm$',views.graph_delete_confirm_view),
|
||||||
url(r'^graph/(\d+)/delete$',views.graph_delete_view),
|
url(r'^graph/(\d+)/delete$',views.graph_delete_view),
|
||||||
|
url(r'^workout/upload/team/s/(?P<successmessage>\w+.*)/c/(?P<message>\w+.*)/$',views.team_workout_upload_view),
|
||||||
|
url(r'^workout/upload/team/c/(?P<message>\w+.*)/$',views.team_workout_upload_view),
|
||||||
|
url(r'^workout/upload/team/s/(?P<successmessage>\w+.*)/$',views.team_workout_upload_view),
|
||||||
|
url(r'^workout/upload/team/$',views.team_workout_upload_view),
|
||||||
url(r'^workout/upload/$',views.workout_upload_view),
|
url(r'^workout/upload/$',views.workout_upload_view),
|
||||||
url(r'^workout/upload/(.+.*)$',views.workout_upload_view),
|
url(r'^workout/upload/c/(?P<message>\w+.*)$',views.workout_upload_view),
|
||||||
url(r'^workout/(?P<id>\d+)/histo$',views.workout_histo_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+)/forcecurve$',views.workout_forcecurve_view),
|
||||||
url(r'^workout/(?P<id>\d+)/unsubscribe$',views.workout_unsubscribe_view),
|
url(r'^workout/(?P<id>\d+)/unsubscribe$',views.workout_unsubscribe_view),
|
||||||
|
|||||||
183
rowers/views.py
183
rowers/views.py
@@ -14,7 +14,10 @@ from django.http import (
|
|||||||
HttpResponseNotFound,Http404
|
HttpResponseNotFound,Http404
|
||||||
)
|
)
|
||||||
from django.contrib.auth import authenticate, login, logout
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from rowers.forms import LoginForm,DocumentsForm,UploadOptionsForm
|
from rowers.forms import (
|
||||||
|
LoginForm,DocumentsForm,UploadOptionsForm,
|
||||||
|
TeamUploadOptionsForm,
|
||||||
|
)
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
@@ -5350,6 +5353,183 @@ def workout_upload_view(request,message="",
|
|||||||
'optionsform': optionsform,
|
'optionsform': optionsform,
|
||||||
'message':message})
|
'message':message})
|
||||||
|
|
||||||
|
# This is the main view for processing uploaded files
|
||||||
|
@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
|
||||||
|
def team_workout_upload_view(request,message="",
|
||||||
|
successmessage="",
|
||||||
|
uploadoptions={
|
||||||
|
'make_plot':False,
|
||||||
|
'plottype':'timeplot',
|
||||||
|
}):
|
||||||
|
|
||||||
|
if 'uploadoptions' in request.session:
|
||||||
|
uploadoptions = request.session['uploadoptions']
|
||||||
|
else:
|
||||||
|
request.session['uploadoptions'] = uploadoptions
|
||||||
|
|
||||||
|
|
||||||
|
myteams = Team.objects.filter(manager=request.user)
|
||||||
|
|
||||||
|
make_plot = uploadoptions['make_plot']
|
||||||
|
plottype = uploadoptions['plottype']
|
||||||
|
|
||||||
|
r = Rower.objects.get(user=request.user)
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = DocumentsForm(request.POST,request.FILES)
|
||||||
|
optionsform = TeamUploadOptionsForm(request.POST)
|
||||||
|
|
||||||
|
rowerform = TeamInviteForm(request.POST)
|
||||||
|
rowerform.fields.pop('email')
|
||||||
|
rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct()
|
||||||
|
if form.is_valid():
|
||||||
|
f = request.FILES['file']
|
||||||
|
res = handle_uploaded_file(f)
|
||||||
|
t = form.cleaned_data['title']
|
||||||
|
if rowerform.is_valid():
|
||||||
|
u = rowerform.cleaned_data['user']
|
||||||
|
if u:
|
||||||
|
r = Rower.objects.get(user=u)
|
||||||
|
else:
|
||||||
|
message = 'Please select a rower'
|
||||||
|
response = render(request,
|
||||||
|
'team_document_form.html',
|
||||||
|
{'form':form,
|
||||||
|
'teams':get_my_teams(request.user),
|
||||||
|
'optionsform': optionsform,
|
||||||
|
'rowerform': rowerform,
|
||||||
|
'message':message,
|
||||||
|
'successmessage':successmessage,
|
||||||
|
})
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
workouttype = form.cleaned_data['workouttype']
|
||||||
|
|
||||||
|
notes = form.cleaned_data['notes']
|
||||||
|
|
||||||
|
if optionsform.is_valid():
|
||||||
|
make_plot = optionsform.cleaned_data['make_plot']
|
||||||
|
plottype = optionsform.cleaned_data['plottype']
|
||||||
|
|
||||||
|
uploadoptions = {
|
||||||
|
'makeprivate':False,
|
||||||
|
'make_plot':make_plot,
|
||||||
|
'plottype':plottype,
|
||||||
|
'upload_to_C2':False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
request.session['uploadoptions'] = uploadoptions
|
||||||
|
|
||||||
|
f1 = res[0] # file name
|
||||||
|
f2 = res[1] # file name incl media directory
|
||||||
|
|
||||||
|
|
||||||
|
id,message,f2 = dataprep.new_workout_from_file(r,f2,
|
||||||
|
workouttype=workouttype,
|
||||||
|
makeprivate=False,
|
||||||
|
title = t,
|
||||||
|
notes='')
|
||||||
|
if not id:
|
||||||
|
url = reverse(team_workout_upload_view,
|
||||||
|
args=[str(message)])
|
||||||
|
response = HttpResponseRedirect(url)
|
||||||
|
return response
|
||||||
|
|
||||||
|
else:
|
||||||
|
if message:
|
||||||
|
successmessage = "The workout was added to the user's account"
|
||||||
|
url = reverse(team_workout_upload_view,
|
||||||
|
kwargs = {
|
||||||
|
'message':message,
|
||||||
|
'successmessage':successmessage,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
successmessage = "The workout was added to the user's account"
|
||||||
|
url = reverse(team_workout_upload_view,
|
||||||
|
kwargs = {
|
||||||
|
'successmessage':successmessage,
|
||||||
|
})
|
||||||
|
|
||||||
|
response = HttpResponseRedirect(url)
|
||||||
|
w = Workout.objects.get(id=id)
|
||||||
|
|
||||||
|
if (make_plot):
|
||||||
|
imagename = f1[:-4]+'.png'
|
||||||
|
fullpathimagename = 'static/plots/'+imagename
|
||||||
|
powerperc = 100*np.array([r.pw_ut2,
|
||||||
|
r.pw_ut1,
|
||||||
|
r.pw_at,
|
||||||
|
r.pw_tr,r.pw_an])/r.ftp
|
||||||
|
|
||||||
|
hrpwrdata = {
|
||||||
|
'hrmax':r.max,
|
||||||
|
'hrut2':r.ut2,
|
||||||
|
'hrut1':r.ut1,
|
||||||
|
'hrat':r.at,
|
||||||
|
'hrtr':r.tr,
|
||||||
|
'hran':r.an,
|
||||||
|
'ftp':r.ftp,
|
||||||
|
'powerperc':serialize_list(powerperc),
|
||||||
|
'powerzones':serialize_list(r.powerzones),
|
||||||
|
}
|
||||||
|
|
||||||
|
# make plot - asynchronous task
|
||||||
|
plotnrs = {
|
||||||
|
'timeplot':1,
|
||||||
|
'distanceplot':2,
|
||||||
|
'pieplot':3,
|
||||||
|
}
|
||||||
|
|
||||||
|
plotnr = plotnrs[plottype]
|
||||||
|
if (workouttype=='water'):
|
||||||
|
plotnr = plotnr+3
|
||||||
|
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
res = handle_makeplot.delay(f1,f2,t,
|
||||||
|
hrpwrdata,plotnr,
|
||||||
|
imagename)
|
||||||
|
else:
|
||||||
|
res = queue.enqueue(handle_makeplot,f1,f2,
|
||||||
|
t,hrpwrdata,
|
||||||
|
plotnr,imagename)
|
||||||
|
|
||||||
|
|
||||||
|
i = GraphImage(workout=w,
|
||||||
|
creationdatetime=timezone.now(),
|
||||||
|
filename=fullpathimagename)
|
||||||
|
i.save()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
response = render(request,
|
||||||
|
'team_document_form.html',
|
||||||
|
{'form':form,
|
||||||
|
'teams':get_my_teams(request.user),
|
||||||
|
'optionsform': optionsform,
|
||||||
|
'rowerform': rowerform,
|
||||||
|
'message':message,
|
||||||
|
'successmessage':successmessage,
|
||||||
|
})
|
||||||
|
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
form = DocumentsForm()
|
||||||
|
optionsform = TeamUploadOptionsForm(initial=uploadoptions)
|
||||||
|
rowerform = TeamInviteForm()
|
||||||
|
rowerform.fields.pop('email')
|
||||||
|
rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct()
|
||||||
|
return render(request, 'team_document_form.html',
|
||||||
|
{'form':form,
|
||||||
|
'teams':get_my_teams(request.user),
|
||||||
|
'optionsform': optionsform,
|
||||||
|
'rowerform':rowerform,
|
||||||
|
'message':message,
|
||||||
|
'successmessage':successmessage,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Ask the user if he really wants to delete the workout
|
# Ask the user if he really wants to delete the workout
|
||||||
@@ -6434,6 +6614,7 @@ def rower_teams_view(request,message='',successmessage=''):
|
|||||||
'successmessage':successmessage,
|
'successmessage':successmessage,
|
||||||
'myinvites':myinvites,
|
'myinvites':myinvites,
|
||||||
})
|
})
|
||||||
|
|
||||||
@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
|
@user_passes_test(iscoachmember,login_url="/",redirect_field_name=None)
|
||||||
def invitation_revoke_view(request,id):
|
def invitation_revoke_view(request,id):
|
||||||
res,text = teams.revoke_invite(request.user,id)
|
res,text = teams.revoke_invite(request.user,id)
|
||||||
|
|||||||
Reference in New Issue
Block a user