Private
Public Access
1
0

Merge branch 'feature/teamcontinued' into develop

This commit is contained in:
Sander Roosendaal
2017-02-15 16:17:19 +01:00
10 changed files with 212 additions and 31 deletions

View File

@@ -228,7 +228,8 @@ def timedeltaconv(x):
# Processes painsled CSV file to database
def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
dosummary=True,title='Workout',
notes='',totaldist=0,totaltime=0):
notes='',totaldist=0,totaltime=0,
makeprivate=False):
message = None
powerperc = 100*np.array([r.pw_ut2,
r.pw_ut1,
@@ -313,12 +314,18 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
workoutstartdatetime = thetimezone.localize(row.rowdatetime).astimezone(utc)
if makeprivate:
privacy = 'private'
else:
privacy = 'visible'
# check for duplicate start times
ws = Workout.objects.filter(starttime=workoutstarttime,
user=r)
if (len(ws) != 0):
message = "Warning: This workout probably already exists in the database"
w = Workout(user=r,name=title,date=workoutdate,
workouttype=workouttype,
duration=duration,distance=totaldist,
@@ -326,15 +333,16 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
starttime=workoutstarttime,
csvfilename=f2,notes=notes,summary=summary,
maxhr=maxhr,averagehr=averagehr,
startdatetime=workoutstartdatetime)
startdatetime=workoutstartdatetime,
privacy=privacy)
w.save()
ts = Team.objects.filter(rower=r)
for t in ts:
w.team.add(t)
if privacy == 'visible':
ts = Team.objects.filter(rower=r)
for t in ts:
w.team.add(t)
# put stroke data in database
res = dataprep(row.df,id=w.id,bands=True,
@@ -422,6 +430,7 @@ def handle_nonpainsled(f2,fileformat,summary=''):
def new_workout_from_file(r,f2,
workouttype='rower',
title='Workout',
makeprivate=False,
notes=''):
message = None
fileformat = get_file_type(f2)
@@ -470,6 +479,7 @@ def new_workout_from_file(r,f2,
dosummary = (fileformat != 'fit')
id,message = save_workout_database(f2,r,
workouttype=workouttype,
makeprivate=makeprivate,
dosummary=dosummary,
title=title)

View File

@@ -76,14 +76,15 @@ class UploadOptionsForm(forms.Form):
('distanceplot','Distance Plot'),
('pieplot','Pie Chart'),
)
make_plot = forms.BooleanField(initial=False)
make_plot = forms.BooleanField(initial=False,required=False)
plottype = forms.ChoiceField(required=False,
choices=plotchoices,
initial='timeplot')
upload_to_C2 = forms.BooleanField(initial=False)
upload_to_C2 = forms.BooleanField(initial=False,required=False)
makeprivate = forms.BooleanField(initial=False,required=False)
class Meta:
fields = ['make_plot','plottype','upload_toc2']
fields = ['make_plot','plottype','upload_toc2','makeprivate']
# This form is used on the Analysis page to add a custom distance/time
# trial and predict the pace

View File

@@ -104,19 +104,27 @@ class Team(models.Model):
('private','private'),
('open','open'),
)
viewchoices = (
('coachonly','Coach Only'),
('allmembers','All Members')
)
name = models.CharField(max_length=150,unique=True,verbose_name='Team Name')
notes = models.CharField(blank=True,max_length=200,verbose_name='Team Purpose')
manager = models.ForeignKey(User)
private = models.CharField(max_length=30,choices=choices,default='open',
verbose_name='Team Type')
viewing = models.CharField(max_length=30,choices=viewchoices,default='allmembers',verbose_name='Sharing Behavior')
def __unicode__(self):
return self.name
class TeamForm(ModelForm):
class Meta:
model = Team
fields = ['name','notes','private']
fields = ['name','notes','private','viewing']
widgets = {
'notes': forms.Textarea,
}
@@ -196,6 +204,11 @@ class Rower(models.Model):
('coach','coach')
)
privacychoices = (
('visible','Visible'),
('hidden','Hidden'),
)
rowerplan = models.CharField(default='basic',max_length=30,
choices=plans)
@@ -203,8 +216,11 @@ class Rower(models.Model):
teamplanexpires = models.DateField(default=timezone.now)
clubsize = models.IntegerField(default=0)
# Friends/Team
friends = models.ManyToManyField("self",blank=True)
privacy = models.CharField(default='visible',max_length=30,
choices=privacychoices)
team = models.ManyToManyField(Team,blank=True)
@@ -351,6 +367,11 @@ class Workout(models.Model):
('4-', '4- (four)'),
('8+', '8+ (eight)'),
)
privacychoices = (
('private','Private'),
('visible','Visible'),
)
user = models.ForeignKey(Rower)
team = models.ManyToManyField(Team,blank=True)
@@ -374,6 +395,8 @@ class Workout(models.Model):
uploadedtosporttracks = models.IntegerField(default=0)
notes = models.CharField(blank=True,null=True,max_length=200)
summary = models.TextField(blank=True)
privacy = models.CharField(default='visible',max_length=30,
choices=privacychoices)
def __str__(self):
@@ -491,7 +514,7 @@ class WorkoutForm(ModelForm):
duration = forms.TimeInput(format='%H:%M:%S.%f')
class Meta:
model = Workout
fields = ['name','date','starttime','duration','distance','workouttype','boattype','notes']
fields = ['name','date','starttime','duration','distance','workouttype','notes','privacy','boattype']
widgets = {
'date': DateInput(),
'notes': forms.Textarea,
@@ -500,9 +523,12 @@ class WorkoutForm(ModelForm):
def __init__(self, *args, **kwargs):
super(WorkoutForm, self).__init__(*args, **kwargs)
# this line to be removed
del self.fields['privacy']
if self.instance.workouttype != 'water':
del self.fields['boattype']
# Used for the rowing physics calculations
class AdvancedWorkoutForm(ModelForm):
class Meta:

View File

@@ -43,7 +43,7 @@ def handle_add_workouts_team(ws,t):
return 1
def update_team(t,name,manager,private,notes):
def update_team(t,name,manager,private,notes,viewing):
if t.manager != manager:
return (0,'You are not the manager of this team')
try:
@@ -51,16 +51,17 @@ def update_team(t,name,manager,private,notes):
t.manager = manager
t.private = private
t.notes = notes
t.viewing = viewing
t.save()
except IntegrityError:
return (0,'Team name duplication')
return (1,'Team Updated')
def create_team(name,manager,private='open',notes=''):
def create_team(name,manager,private='open',notes='',viewing='allmembers'):
# needs some error testing
try:
t = Team(name=name,manager=manager,notes=notes,
private=private)
private=private,viewing=viewing)
t.save()
r = Rower.objects.get(user=manager)
res = add_member(t.id,r)

View File

@@ -62,7 +62,7 @@
<td> {{ workout.date |truncatechars:15}} </td>
<td> {{ workout.starttime }} </td>
<td>
{% if workout.user.user == user %}
{% if workout.user.user == user or user == team.manager %}
{% if workout.name != '' %}
<a href="/rowers/workout/{{ workout.id }}/edit">{{ workout.name }}</a> </td>
{% else %}

View File

@@ -4,9 +4,11 @@
{% block title %}New Team{% endblock %}
{% block content %}
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
<div class="grid_12 alpha">
<h1>Create a new Team</h1>
</div>
<div id="left" class="grid_6 alpha">
<h1>Create a new Team</h1>
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
@@ -21,7 +23,14 @@
<input class="button green" type="submit" value="Submit">
</div>
</div>
<div id="right" class="grid_6 omega">
<ul>
<li>Team Type: A private team is invisible on the Teams Management page, except for its members. The only way to add members is for the manager to send an invitation. An open team is visible for all rowsandall.com users. In addition to the invitation mechanism, any user can request to be added to this team. The team manager will always have to approve membership.</li>
<li>Sharing Behavior: When set to "All Members", all members of a team will see each other's workouts. This is the recommended setting. If te sharing bhavior is set to "Coach Only", team members only see their own workouts. The coach sees all team members' workouts.</li>
<li>These settings can be changed at any point in time through the Team Edit page</li>
</ul>
</div>
</form>

View File

@@ -4,9 +4,11 @@
{% block title %}New Team{% endblock %}
{% block content %}
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
<div class="grid_12 alpha">
<h1>Edit Team {{ team.name }}</h1>
</div>
<div id="left" class="grid_6 alpha">
<h1>Edit Team {{ team.name }}</h1>
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
@@ -21,6 +23,13 @@
<input class="button green" type="submit" value="Submit">
</div>
</div>
<div id="right" class="grid_6 omega">
<ul>
<li>Team Type: A private team is invisible on the Teams Management page, except for its members. The only way to add members is for the manager to send an invitation. An open team is visible for all rowsandall.com users. In addition to the invitation mechanism, any user can request to be added to this team. The team manager will always have to approve membership.</li>
<li>Sharing Behavior: When set to "All Members", all members of a team will see each other's workouts. This is the recommended setting. If te sharing bhavior is set to "Coach Only", team members only see their own workouts. The coach sees all team members' workouts.</li>
<li>These settings can be changed at any point in time through the Team Edit page</li>
</ul>
</div>

View File

@@ -69,7 +69,16 @@
{{ form.as_table }}
</table>
{% csrf_token %}
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
<div class="grid_2 prefix_2 alpha tooltip">
{% if workout.privacy == 'visible' %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/setprivate">Set Private</a>
<span class="tooltiptext">Only you can see this workout</span>
{% else %}
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/makepublic">Make Public</a>
<span class="tooltiptext">Make this workout visible to your teams and followers</span>
{% endif %}
</div>
<div id="formbutton" class="grid_1 suffix_1 omega">
<input class="button green" type="submit" value="Save">
</div>
</form>

View File

@@ -157,6 +157,8 @@ urlpatterns = [
url(r'^workout/(?P<id>\d+)/edit/c/(?P<message>.+.*)$',views.workout_edit_view),
url(r'^workout/(?P<id>\d+)/edit/s/(?P<successmessage>.+.*)$',views.workout_edit_view),
url(r'^workout/(?P<id>\d+)/edit$',views.workout_edit_view),
url(r'^workout/(?P<id>\d+)/setprivate$',views.workout_setprivate_view),
url(r'^workout/(?P<id>\d+)/makepublic$',views.workout_makepublic_view),
url(r'^workout/(?P<id>\d+)/advanced/c/(?P<message>.+.*)$',views.workout_advanced_view),
url(r'^workout/(?P<id>\d+)/advanced/s/(?P<successmessage>.+.*)$',views.workout_advanced_view),
url(r'^workout/(?P<id>\d+)/geeky$',views.workout_geeky_view),

View File

@@ -302,7 +302,8 @@ def sendmail(request):
def checkworkoutuser(user,workout):
try:
r = Rower.objects.get(user=user)
return (workout.user == r)
managers = [team.manager for team in workout.team.all()]
return (workout.user == r or user in managers)
except Rower.DoesNotExist:
return(False)
@@ -1884,7 +1885,71 @@ def workout_recalcsummary_view(request,id=0):
})
return HttpResponseRedirect(url)
@login_required()
def workout_makepublic_view(request,id,
message='',
successmessage=''):
try:
row = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
url = reverse(workouts_view,args=[str(message)])
return HttpResponseRedirect(url)
row.privacy = 'visible'
row.save()
rr = Rower.objects.get(user=request.user)
teams = rr.team.all()
for team in teams:
row.team.add(team)
message = "Workout set to public. Your followers and team members will see it"
url = reverse(workout_edit_view,
kwargs = {
'id':str(id),
'successmessage':str(message),
})
return HttpResponseRedirect(url)
@login_required()
def workout_setprivate_view(request,id,
message='',
successmessage=''):
try:
row = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
if (checkworkoutuser(request.user,row)==False):
message = "You are not allowed to edit this workout"
url = reverse(workouts_view,args=[str(message)])
return HttpResponseRedirect(url)
row.privacy = 'private'
row.save()
for team in row.team.all():
row.team.remove(team)
message = "Workout set to private. Only you will see it"
url = reverse(workout_edit_view,
kwargs = {
'id':str(id),
'successmessage':str(message),
})
return HttpResponseRedirect(url)
# List Workouts
@login_required()
def workouts_view(request,message='',successmessage='',
@@ -1928,9 +1993,14 @@ def workouts_view(request,message='',successmessage='',
except Team.DoesNotExist:
raise Http404("Team doesn't exist")
workouts = Workout.objects.filter(team=theteam,
if theteam.viewing == 'allmembers' or theteam.manager == request.user:
workouts = Workout.objects.filter(team=theteam,
startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime")
elif theteam.viewing == 'coachonly':
workouts = Workout.objects.filter(team=theteam,user=r,
startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date","-starttime")
else:
@@ -2063,6 +2133,9 @@ def workout_view(request,id=0):
try:
# check if valid ID exists (workout exists)
row = Workout.objects.get(id=id)
if row.privacy == 'private':
raise Http404("Not allowed to view this workout")
g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")
r = Rower.objects.get(id=row.user.id)
u = User.objects.get(id=r.user.id)
@@ -3259,6 +3332,10 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
try:
boattype = request.POST['boattype']
except KeyError:
boattype = Workout.objects.get(id=id).boattype
try:
privacy = request.POST['privacy']
except KeyError:
privacy = Workout.objects.get(id=id).privacy
startdatetime = (str(date) + ' ' + str(starttime))
startdatetime = datetime.datetime.strptime(startdatetime,
@@ -3277,6 +3354,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
row.notes = notes
row.duration = duration
row.distance = distance
row.boattype = boattype
row.privacy = privacy
row.save()
# change data in csv file
@@ -4103,7 +4181,26 @@ def workout_getc2workout_view(request,c2id):
return HttpResponseRedirect(url)
# This is the main view for processing uploaded files
@login_required()
@login_required()
def workout_upload_view(request,message="",
uploadoptions={
'makeprivate':False,
'make_plot':False,
'upload_to_C2':False,
'plottype':'timeplot',
}):
if 'uploadoptions' in request.session:
uploadoptions = request.session['uploadoptions']
else:
request.session['uploadoptions'] = uploadoptions
makeprivate = uploadoptions['makeprivate']
make_plot = uploadoptions['make_plot']
plottype = uploadoptions['plottype']
upload_toc2 = uploadoptions['upload_to_C2']
r = Rower.objects.get(user=request.user)
if request.method == 'POST':
@@ -4115,10 +4212,22 @@ def workout_upload_view(request,message=""):
t = form.cleaned_data['title']
workouttype = form.cleaned_data['workouttype']
notes = form.cleaned_data['notes']
make_plot = request.POST.getlist('make_plot')
plottype = request.POST['plottype']
notes = form.cleaned_data['notes']
if optionsform.is_valid():
make_plot = optionsform.cleaned_data['make_plot']
plottype = optionsform.cleaned_data['plottype']
upload_to_c2 = optionsform.cleaned_data['upload_to_C2']
makeprivate = optionsform.cleaned_data['makeprivate']
uploadoptions = {
'makeprivate':makeprivate,
'make_plot':make_plot,
'plottype':plottype,
'upload_to_C2':upload_to_c2,
}
request.session['uploadoptions'] = uploadoptions
f1 = res[0] # file name
@@ -4126,6 +4235,7 @@ def workout_upload_view(request,message=""):
id,message = dataprep.new_workout_from_file(r,f2,
workouttype=workouttype,
makeprivate=makeprivate,
title = t,
notes='')
@@ -4266,7 +4376,7 @@ def workout_upload_view(request,message=""):
return response
else:
form = DocumentsForm()
form = DocumentsForm()
optionsform = UploadOptionsForm(initial=uploadoptions)
return render(request, 'document_form.html',
{'form':form,
@@ -5432,7 +5542,9 @@ def team_edit_view(request,id=0):
name = cd['name']
notes = cd['notes']
manager = request.user
private = cd['private']
private = cd['private']
viewing = cd['viewing']
res,message=teams.update_team(t,name,manager,private,notes,
viewing)
if res:
url = reverse(team_view,
@@ -5470,7 +5582,9 @@ def team_create_view(request):
name = cd['name']
notes = cd['notes']
manager = request.user
private = cd['private']
private = cd['private']
viewing = cd['viewing']
res,message=teams.create_team(name,manager,private,notes,
viewing)
url = reverse(rower_teams_view)
response = HttpResponseRedirect(url)