Private
Public Access
1
0

Merge branch 'develop' into feature/workoutslist

This commit is contained in:
Sander Roosendaal
2021-12-28 13:15:22 +01:00
18 changed files with 76 additions and 543 deletions

View File

@@ -1286,6 +1286,15 @@ class AnalysisChoiceForm(forms.Form):
label='Include Rest Strokes')
def __init__(self, *args, **kwargs):
super(AnalysisChoiceForm, self).__init__(*args, **kwargs)
if 'initial' in kwargs and kwargs['initial']['function'] == 'compare':
self.fields['xaxis'].initial = 'time'
self.fields['yaxis1'].initial = 'hr'
self.fields['plottype'].initial = 'line'
class BoxPlotChoiceForm(forms.Form):
yparam = forms.ChoiceField(choices=parchoices,initial='spm',

View File

@@ -13,13 +13,14 @@
on behalf of {{ name }}.
</p>
<p>
By accepting the invite, you are agreeing with the sharing
By accepting the invite, you are agreeing with the sharing
of personal data according to our privacy policy.
</p>
<p>
To accept the login to the
site and you will find the invitation here on the Teams page:
<a href="{{ siteurl }}/rowers/me/teams">{{ siteurl }}/rowers/me/teams</a>
<a href="{{ siteurl }}/rowers/me/teams">{{ siteurl }}/rowers/me/teams</a>,
including the email address of {{ name }}, if you need a contact.
</p>
<p>
You can also click the direct link:

View File

@@ -10,9 +10,11 @@
</li>
<li id="compare">
{% if team %}
<a href="/rowers/team-compare-select/team/{{ team.id }}/"><i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
<a href="/rowers/user-analysis-select/compare/team/{{ team.id }}/">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
{% else %}
<a href="/rowers/team-compare-select/team/0/"><i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
<a href="/rowers/user-analysis-select/compare/team/0/">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
{% endif %}
</li>
<li>

View File

@@ -48,7 +48,7 @@
</a>
</li>
<li id="compare">
<a href="/rowers/team-compare-select/workout/{{ workout.id|encode }}/">
<a href="/rowers/user-analysis-select/compare/workout/{{ workout.id|encode }}/">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare
</a>
</li>

View File

@@ -10,10 +10,10 @@
</li>
<li id="compare">
{% if team %}
<a href="/rowers/team-compare-select/team/{{ team.id }}/">
<a href="/rowers/user-analysis-select/compare/team/{{ team.id }}/">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
{% else %}
<a href="/rowers/team-compare-select/team/0/">
<a href="/rowers/user-analysis-select/compare/team/0/">
<i class="fas fa-balance-scale fa-fw"></i>&nbsp;Compare</a>
{% endif %}
</li>

View File

@@ -1,144 +0,0 @@
{% extends "newbase.html" %}
{% load static %}
{% load rowerfilters %}
{% block title %}Workouts{% endblock %}
{% block main %}
<script>
function toggle(source) {
checkboxes = document.querySelectorAll("input[name='workouts']");
for(var i=0, n=checkboxes.length;i<n;i++) {
checkboxes[i].checked = source.checked;
}
}
</script>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(function() {
// Get the form fields and hidden div
var modality = $("#id_modality");
var hidden = $("#id_waterboattype");
// Hide the fields.
// Use JS to do this in case the user doesn't have JS
// enabled.
hidden.hide();
if (modality.val() == 'water') {
hidden.show();
}
// Setup an event listener for when the state of the
// checkbox changes.
modality.change(function() {
// Check to see if the checkbox is checked.
// If it is, show the fields and populate the input.
// If not, hide the fields.
var Value = modality.val();
if (Value=='water') {
// Show the hidden fields.
hidden.show();
} else {
// Make sure that the hidden fields are indeed
// hidden.
hidden.hide();
// You may also want to clear the value of the
// hidden fields here. Just in case somebody
// shows the fields, enters data to them and then
// unticks the checkbox.
//
// This would do the job:
//
// $("#hidden_field").val("");
}
});
});
</script>
<h1>{{ team.name }} Compare Workouts</h1>
<ul class="main-content">
<li class="grid_4">
<p>Select two or more workouts on the left, set your plot settings,
and press submit</p>
<p>
You can use the date and search forms to search through all
workouts from this team.
</p>
<p>
TIP: Agree with your team members to put tags (e.g. '8x500m')
in the notes section of
your workouts. That makes it easy to search.
</p>
</li>
<li class="grid_2">
<form enctype="multipart/form-data"
action=""
method="post">
<table>
{{ dateform.as_table }}
</table>
<table>
{{ modalityform.as_table }}
</table>
{% csrf_token %}
<p>
<input name='modalityform' class="button green" type="submit" value="Filter">
</p>
</form>
</li>
<li class="grid_2">
<form id="searchform"
action=""
method="get" accept-charset="utf-8">
{{ searchform }}
<input type="submit" value="GO"></input>
</form>
</li>
<li class="grid_2 maxheight">
{% if workouts %}
<form enctype="multipart/form-data"
action="/rowers/multi-compare/"
method="post">
<input type="checkbox" onClick="toggle(this)" /> Toggle All<br/>
<table width="100%" class="listtable">
{{ form.as_table }}
</table>
{% else %}
<p> No workouts found </p>
{% endif %}
</li>
<li class="grid_2">
<p>
{% csrf_token %}
<table>
{{ chartform.as_table }}
</table>
</p>
<p>
<input name="chartform" type="submit" value="Compare">
</p>
</form>
</li>
</ul>
{% endblock %}
{% block sidebar %}
{% include 'menu_workouts.html' %}
{% endblock %}

View File

@@ -6,7 +6,7 @@
</div>
<div class="grid_2">
<p>
<a class="button gray small" href="/rowers/team-compare-select/team/{{ teamid }}/">Multi Compare</a>
<a class="button gray small" href="/rowers/user-analysis-select/compare/{{ teamid }}/">Multi Compare</a>
</p>
</div>
<div class="grid_2">

View File

@@ -21,7 +21,7 @@
<a href="/rowers/team/{{ team.id }}/">{{ team.name }}</a>
</td>
<td>
<a class="button small red" href="/rowers/team/{{ team.id }}/leaveconfirm/">Leave</a>
<a href="/rowers/team/{{ team.id }}/leaveconfirm/">Leave</a>
</td>
</tr>
{% endfor %}
@@ -29,7 +29,7 @@
</table>
</li>
{% endif %}
{% if otherteams %}
<li class="grid_2">
<h2>Open Groups</h2>
@@ -73,7 +73,7 @@
<a href="/rowers/team/{{ team.id }}/">{{ team.name }}</a>
</td>
<td>
<a class="button small red" href="/rowers/team/{{ team.id }}/deleteconfirm/">Delete</a>
<a href="/rowers/team/{{ team.id }}/deleteconfirm/">Delete</a>
</td>
</tr>
{% endfor %}
@@ -98,7 +98,7 @@
{{ coach.user.first_name }} {{ coach.user.last_name }}
</td>
<td>
<a class="button small red"
<a
href="/rowers/coaches/{{ coach.id }}/dropcoachconfirm/">Remove
</a>
</td>
@@ -124,7 +124,7 @@
{{ coachee.user.first_name }} {{ coachee.user.last_name }}
</td>
<td>
<a class="button small red"
<a
href="/rowers/coaches/{{ coachee.id }}/dropconfirm/">Remove
</a>
</td>
@@ -138,11 +138,11 @@
<li class="grid_2">
<h2>Group Invitations and Requests</h2>
<p>This section lists open invites to join a group. By accepting
a group invite, you are agreeing with the sharing
a group invite, you are agreeing with the sharing
of personal data between group members and coaches according to
our <a href="/rowers/legal/">privacy policy</a>.
</p>
<p>As a group manager, by accepting a group invite, you are agreeing
with our <a href="/rowers/legal/">privacy policy</a> regarding groups and
personal data owned by group members.</p>
@@ -163,10 +163,10 @@
<td><a href="/rowers/team/{{ i.team.id }}/">{{ i.team.name }}</a></td>
<td>{{ i.team.manager.first_name }} {{ i.team.manager.last_name }}</td>
<td>{{ user.first_name }} {{ user.last_name }}</td>
<td><a class="button small green" href="/rowers/me/invitation/{{ i.code }}/">Accept</a>
<td><a href="/rowers/me/invitation/{{ i.code }}/">Accept</a>
</td>
<td>
<a class="button small red" href="/rowers/me/invitation/{{ i.id }}/reject/">Reject</a>
<a href="/rowers/me/invitation/{{ i.id }}/reject/">Reject</a>
</td>
</tr>
{% endfor %}
@@ -184,9 +184,9 @@
<td><a href="/rowers/team/{{ i.team.id }}/">{{ i.team.name }}</a></td>
<td>{{ i.team.manager.first_name }} {{ i.team.manager.last_name }}</td>
<td>{{ i.user.first_name }} {{ i.user.last_name }}</td>
<td><a class="button small green" href="/rowers/me/request/{{ i.code }}/">Accept</a>
<td><a href="/rowers/me/request/{{ i.code }}/">Accept</a>
<td>
<a class="button small red" href="/rowers/me/request/{{ i.id }}/reject/">Reject</a>
<a href="/rowers/me/request/{{ i.id }}/reject/">Reject</a>
</td>
</tr>
{% endfor %}
@@ -201,7 +201,7 @@
{% endif %}
<td>&nbsp;
<td>
<a class="button small red" href="/rowers/me/invitation/{{ i.id }}/revoke/">Revoke</a>
<a href="/rowers/me/invitation/{{ i.id }}/revoke/">Revoke</a>
</td>
</tr>
{% endfor %}
@@ -218,7 +218,7 @@
<table>
{{ form.as_table }}
</table>
<input class="button green" type="submit" value="Submit">
<input class="button" type="submit" value="Submit">
</form>
{% endif %}
{% if mycoachrequests or mycoachoffers or coachoffers or coachrequests %}
@@ -226,16 +226,17 @@
<h2>Coaching Offers and Requests</h2>
<p>This section lists open offers and requests related to coaching.
By accepting a coaching offer, the coach can run
analysis, add workouts and edit settings on behalf of the athlete.
analysis, add workouts and edit settings on behalf of the athlete.
You agree to the sharing
of personal data between athletes and coaches according to
our <a href="/rowers/legal/">privacy policy</a>.
</p>
</p>
<table width="90%" class="listtable">
<thead>
<tr>
<th>Coach</th>
<th>User</th>
<th>E-mail</th>
<th>Action</th>
<th>&nbsp;</th>
</tr>
@@ -245,12 +246,13 @@
<tr>
<td>{{ i.coach.user.first_name }} {{ i.coach.user.last_name }}</td>
<td>{{ i.user.first_name }} {{ i.user.last_name }}</td>
<td>{{ i.user.email }}</td>
<td><a
class="button small green"
href="/rowers/me/coachrequest/{{ i.code }}/accept">Accept</a>
</td>
<td>
<a class="button small red" href="/rowers/me/coachrequest/{{ i.id }}/reject/">Reject</a>
<a href="/rowers/me/coachrequest/{{ i.id }}/reject/">Reject</a>
</td>
</tr>
{% endfor %}
@@ -261,7 +263,7 @@
<td>&nbsp;
</td>
<td>
<a class="button small red" href="/rowers/me/coachoffer/{{ i.id }}/revoke/">Revoke</a>
<a href="/rowers/me/coachoffer/{{ i.id }}/revoke/">Revoke</a>
</td>
</tr>
{% endfor %}
@@ -272,7 +274,7 @@
<td>&nbsp;</td>
<td>
<a
class="button small red"
href="/rowers/me/coachrequest/{{ i.id }}/revoke/">Revoke</a>
</td>
</tr>
@@ -282,12 +284,12 @@
<td>{{ i.coach.user.first_name }} {{ i.coach.user.last_name }}</td>
<td>{{ i.user.first_name }} {{ i.user.last_name }}</td>
<td><a
class="button small green"
href="/rowers/me/coachoffer/{{ i.code }}/accept/">Accept</a>
</td>
<td>
<a
class="button small red"
href="/rowers/me/coachoffer/{{ i.id }}/revoke/">Reject</a>
</td>
</tr>
@@ -312,14 +314,14 @@
<td>{{ a.user.first_name }} {{ a.user.last_name }}</td>
<td>
<a
class="button small green"
href="/rowers/me/coachoffer/{{ a.user.id }}/">Offer Coaching</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</li>
</li>
{% endif %}
{% if potentialcoaches %}
<li class="grid_2">
@@ -337,7 +339,7 @@
<td>{{ c.first_name }} {{ c.last_name }}</td>
<td>
<a
class="button small green"
href="/rowers/me/coachrequest/{{ c.id }}/">Request Coaching</a>
</td>
</tr>

View File

@@ -36,7 +36,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile
from io import StringIO
from django.test.client import RequestFactory
from rowers.views import c2_open, multi_compare_view
from rowers.views import c2_open
from rowers.forms import (

View File

@@ -11,70 +11,6 @@ nu = datetime.datetime.now()
from rowers.views import *
from rowers.views.analysisviews import histodata
class WorkoutCompareTest(TestCase):
def setUp(self):
self.u = UserFactory()
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
self.u.save()
def tearDown(self):
for workout in self.user_workouts:
try:
os.remove(workout.csvfilename)
except (IOError, FileNotFoundError, OSError):
pass
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_workouts_compare(self, mocked_sqlalchemy,
mocked_getsmallrowdata_db):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/team-compare-select/workout/'+encoded1+'/team/0/user/1/'
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
def test_workouts_compare_submit(self, mocked_sqlalchemy,
mocked_getsmallrowdata_db):
login = self.c.login(username=self.u.username,password=self.password)
self.assertTrue(login)
form_data = {
'chartform':'Compare',
'plottype':'scatter',
'teamid':0,
'workouts':['1','2','3'],
'xparam':'distance',
'yparam':'hr',
}
form = WorkoutMultipleCompareForm(form_data)
chartform = ChartParamChoiceForm(form_data)
self.assertTrue(form.is_valid())
self.assertTrue(chartform.is_valid())
response = self.c.post('/rowers/multi-compare/',form_data)
self.assertEqual(response.status_code,200)
class ListWorkoutTest(TestCase):

View File

@@ -214,70 +214,6 @@ class WorkoutViewTest(TestCase):
expected_url=expected_url,
status_code=302,target_status_code=200)
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
@patch('rowers.middleware.myqueue')
def test_compares(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
mocked_myqueue):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
session = self.c.session
session['ids'] = [self.werg1.id,self.werg2.id]
session.save()
response = self.c.get('/')
url = reverse('team_comparison_select')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
d1 = self.werg1.date-datetime.timedelta(days=2)
d2 = self.werg2.date+datetime.timedelta(days=2)
form_data = {
'startdate': d1.strftime('%Y-%m-%d'),
'enddate': d2.strftime('%Y-%m-%d'),
'modality':'water',
'waterboattype':['1x'],
}
form = DateRangeForm(form_data)
self.assertTrue(form.is_valid())
form = TrendFlexModalForm(form_data)
self.assertTrue(form.is_valid())
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
url = reverse('multi_compare_view',kwargs={
'userid':self.u.id,
'id':encoder.encode_hex(self.werg1.id),
})
form_data = {
'xparam':'time',
'yparam':'power',
'plottype':'line',
'teamid': '',
}
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
session['plottype'] = 'scatter'
session['xparam'] = 'time'
session['yparam'] = 'hr'
session.save()
response = self.c.get('/')
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')

View File

@@ -16,6 +16,7 @@ from django.db import transaction
import json
from rowers.views.workoutviews import plannedsession_compare_view
from rowers.views.analysisviews import analysis_new
from rowers.views.otherviews import download_fit
from rowers.opaque import encoder
from django.utils.crypto import get_random_string
@@ -443,7 +444,11 @@ class SessionLinkTest(TestCase):
url = reverse(plannedsession_compare_view,kwargs={'id':ps.id,'userid':self.u.id})
response = self.c.get(url,follow=True)
expected_url = reverse('multi_compare_view',kwargs={'userid':self.u.id,'id':encoder.encode_hex(w.id)})
expected_url = reverse('analysis_new',
kwargs={'function':'compare',
'id':encoder.encode_hex(w.id),
'session':ps.id,
})
self.assertRedirects(response,expected_url=expected_url,
status_code=302,target_status_code=200)
@@ -473,7 +478,7 @@ class SessionLinkTest(TestCase):
session.save()
request.user = self.u
response = multi_compare_view(request,id=str(w.id))
response = analysis_new(request,id=encoder.encode_hex(w.id))
self.assertEqual(response.status_code,200)
# and adding a get
@@ -491,7 +496,7 @@ class SessionLinkTest(TestCase):
session.save()
request.user = self.u
response = multi_compare_view(request,id=str(w.id))
response = analysis_new(request,id=encoder.encode_hex(w.id))
self.assertEqual(response.status_code,200)

View File

@@ -169,70 +169,6 @@ class TeamTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
@patch('rowers.middleware.myqueue')
def test_compares(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
mocked_myqueue):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
session = self.c.session
session['ids'] = [self.werg1.id,self.werg2.id]
session.save()
response = self.c.get('/')
url = reverse('team_comparison_select',kwargs={'teamid':self.t.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
d1 = self.werg1.date-timedelta(days=2)
d2 = self.werg2.date+timedelta(days=2)
form_data = {
'startdate': d1.strftime('%Y-%m-%d'),
'enddate': d2.strftime('%Y-%m-%d'),
'modality':'water',
'waterboattype':['1x'],
}
form = DateRangeForm(form_data)
self.assertTrue(form.is_valid())
form = TrendFlexModalForm(form_data)
self.assertTrue(form.is_valid())
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
url = reverse('multi_compare_view',kwargs={
'userid':self.u.id,
'id':encoder.encode_hex(self.werg1.id),
})
form_data = {
'xparam':'time',
'yparam':'power',
'plottype':'line',
'teamid': '',
}
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
session['plottype'] = 'scatter'
session['xparam'] = 'time'
session['yparam'] = 'hr'
session.save()
response = self.c.get('/')
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
def test_teamsview(self):

View File

@@ -124,8 +124,6 @@ class URLTests(TestCase):
'/rowers/sessions/multicreate/',
'/rowers/sessions/print/',
'/rowers/sessions/teamcreate/',
'/rowers/team-compare-select/',
'/rowers/team-compare-select/workout/'+encoded1+'/',
'/rowers/workout/'+encoded1+'/',
'/rowers/workout/'+encoded1+'/adddistanceplot/',
'/rowers/workout/'+encoded1+'/adddistanceplot2/',

View File

@@ -23,7 +23,6 @@
22,24,courses_view,see race courses,TRUE,200,FALSE,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
23,25,course_upload_view,upload a new course,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
24,26,addmanual_view,upload a manual workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
25,27,team_comparison_select,compare with a team member workout,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,TRUE,TRUE,TRUE,TRUE,
26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE,
27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
@@ -97,7 +96,6 @@
111,137,workout_recalcsummary_view,recalculates workout summary,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE,
112,138,workout_sporttracks_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE,
115,141,workout_tp_upload_view,uploads workout to C2,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE,
116,142,multi_compare_view,compare workouts ,TRUE,302,basic,302,403,basic,302,403,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
117,145,alerts_view,view alerts,TRUE,302,basic,200,403,basic,403,403,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
118,147,AlertDelete,delete alert,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
119,148,alert_edit_view,edit alert,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
1 id view function anonymous anonymous_response own own_response own_nonperm member member_response member_nonperm coachee coachee_response coachee_nonperm is_staff userid workoutid dotest realtest kwargs
23 22 24 courses_view see race courses TRUE 200 FALSE 200 302 FALSE 200 302 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
24 23 25 course_upload_view upload a new course TRUE 302 basic 200 302 FALSE 200 302 FALSE 200 302 FALSE FALSE FALSE TRUE TRUE
25 24 26 addmanual_view upload a manual workout TRUE 302 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE TRUE TRUE
25 27 team_comparison_select compare with a team member workout TRUE 302 pro 200 302 pro 200 302 coach 200 302 FALSE TRUE TRUE TRUE TRUE
26 26 28 workouts_join_view join workouts TRUE 302 pro 302 302 pro 403 403 coach 302 403 FALSE TRUE FALSE TRUE TRUE
27 27 29 workouts_join_select select workouts to join TRUE 404 pro 200 302 pro 403 403 coach 200 403 FALSE TRUE FALSE TRUE TRUE
28 29 31 analysis_new analysis front page TRUE 302 pro 200 302 FALSE 200 302 coach 200 302 FALSE TRUE FALSE TRUE TRUE
96 111 137 workout_recalcsummary_view recalculates workout summary TRUE 403 basic 302 403 basic 403 403 coach 302 403 FALSE FALSE TRUE TRUE TRUE
97 112 138 workout_sporttracks_upload_view uploads workout to C2 TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE TRUE FALSE FALSE
98 115 141 workout_tp_upload_view uploads workout to C2 TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE TRUE FALSE FALSE
116 142 multi_compare_view compare workouts TRUE 302 basic 302 403 basic 302 403 coach 302 302 FALSE FALSE TRUE TRUE TRUE
99 117 145 alerts_view view alerts TRUE 302 basic 200 403 basic 403 403 coach 200 302 FALSE TRUE FALSE TRUE TRUE
100 118 147 AlertDelete delete alert TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE
101 119 148 alert_edit_view edit alert TRUE 200 basic 200 302 basic 200 302 coach 200 302 FALSE FALSE FALSE FALSE FALSE

View File

@@ -308,24 +308,16 @@ urlpatterns = [
re_path(r'^standards/upload/(?P<id>\d+)/$',views.standards_upload_view,name='standards_upload_view'),
re_path(r'^workout/addmanual/(?P<raceid>\d+)/$',views.addmanual_view,name='addmanual_view'),
re_path(r'^workout/addmanual/$',views.addmanual_view,name='addmanual_view'),
re_path(r'^team-compare-select/workout/(?P<id>\d+)/team/(?P<teamid>\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/workout/(?P<id>\b[0-9A-Fa-f]+\b)/team/(?P<teamid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/workout/(?P<id>\b[0-9A-Fa-f]+\b)/team/(?P<teamid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/workout/(?P<id>\b[0-9A-Fa-f]+\b)/team/(?P<teamid>\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/workout/(?P<id>\b[0-9A-Fa-f]+\b)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/team/(?P<teamid>\d+)/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/team/(?P<teamid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/user/(?P<userid>\d+)/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^team-compare-select/$',views.team_comparison_select,name='team_comparison_select'),
re_path(r'^workouts-join/$',views.workouts_join_view,name='workouts_join_view'),
re_path(r'^workouts-join/user/(?P<userid>\d+)$',views.workouts_join_view,name='workouts_join_view'),
re_path(r'^workouts-join-select/$',views.workouts_join_select,name='workouts_join_select'),
re_path(r'^workouts-join-select/user/(?P<userid>\d+)/$',views.workouts_join_select,name='workouts_join_select'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/session/(?P<session>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/user/(?P<userid>\d+)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/user/(?P<userid>\d+)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/team/(?P<teamid>\d+)/$',views.analysis_new,name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/$',views.analysis_new,name='analysis_new'),
@@ -518,10 +510,6 @@ urlpatterns = [
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/recalcsummary/$',views.workout_recalcsummary_view,name='workout_recalcsummary_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/sporttracksuploadw/$',views.workout_sporttracks_upload_view,name='workout_sporttracks_upload_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/tpuploadw/$',views.workout_tp_upload_view,name='workout_tp_upload_view'),
re_path(r'^multi-compare/workout/(?P<id>\b[0-9A-Fa-f]+\b)/user/(?P<userid>\d+)/$',views.multi_compare_view,
name='multi_compare_view'),
re_path(r'^multi-compare/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.multi_compare_view,name='multi_compare_view'),
re_path(r'^multi-compare/$',views.multi_compare_view,name='multi_compare_view'),
re_path(r'^alerts/user/(?P<userid>\d+)/$',views.alerts_view,name='alerts_view'),
re_path(r'^alerts/$',views.alerts_view,name='alerts_view'),
re_path(r'^alerts/(?P<pk>\d+)/delete/$',views.AlertDelete.as_view(),name='alert_delete_view'),

View File

@@ -8,6 +8,7 @@ from rowers.views.statements import *
import collections
import simplejson
from jinja2 import Template,Environment,FileSystemLoader
from rowers.rower_rules import can_view_session
def floatformat(x,prec=2): # pragma: no cover
return '{x}'.format(x=round(x,prec))
@@ -34,7 +35,7 @@ defaultoptions = {
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def analysis_new(request,userid=0,function='boxplot',teamid=0,id=''):
def analysis_new(request,userid=0,function='boxplot',teamid=0,id='',session=0):
r = getrequestrower(request, userid=userid)
user = r.user
userid = user.id
@@ -52,6 +53,13 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0,id=''):
except Team.DoesNotExist:
theteam = None
try:
thesession = PlannedSession.objects.get(id=session)
if not can_view_session(user,thesession):
raise PermissionDenied("you cannot view this session")
except PlannedSession.DoesNotExist:
thesession = None
if 'options' in request.session:
options = request.session['options']
@@ -199,6 +207,8 @@ def analysis_new(request,userid=0,function='boxplot',teamid=0,id=''):
startdatetime__lte=enddate,
workouttype__in=modalities,
)
elif thesession is not None:
workouts = get_workouts_session(r,thesession)
else:
workouts = Workout.objects.filter(user=r,
startdatetime__gte=startdate,

View File

@@ -2024,163 +2024,19 @@ def plannedsession_compare_view(request,id=0,userid=0):
request.session['plottype'] = plottype
request.session['ps'] = ps.id
teams = ps.team.all()
if ids:
url = reverse('multi_compare_view',
kwargs={'userid':userid,'id':encoder.encode_hex(ids[0])})
url = reverse('analysis_new',
kwargs={
'session':ps.id,
'id':encoder.encode_hex(ids[0]),
'function':'compare'})
else:
url = reverse('plannedsession_view',kwargs={'id':ps.id})
return HttpResponseRedirect(url)
# Team comparison
@login_required()
def multi_compare_view(request,id=0,userid=0):
promember=0
if not request.user.is_anonymous:
r = getrower(request.user)
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember=1
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
chartform = ChartParamChoiceForm(request.POST)
if form.is_valid() and chartform.is_valid():
cd = form.cleaned_data
workouts = cd['workouts']
xparam = chartform.cleaned_data['xparam']
yparam = chartform.cleaned_data['yparam']
plottype = chartform.cleaned_data['plottype']
teamid = chartform.cleaned_data['teamid']
ids = [int(w.id) for w in workouts]
request.session['ids'] = ids
labeldict = {
int(w.id): w.__str__() for w in workouts
}
else: # pragma: no cover
return HttpResponse("Form is not valid")
elif request.method == 'POST' and 'ids' in request.session:
chartform = ChartParamChoiceForm(request.POST)
if chartform.is_valid():
xparam = chartform.cleaned_data['xparam']
yparam = chartform.cleaned_data['yparam']
plottype = chartform.cleaned_data['plottype']
teamid = chartform.cleaned_data['teamid']
ids = request.session['ids']
request.session['ids'] = ids
workouts = []
for id in ids:
try:
workouts.append(Workout.objects.get(id=id))
except Workout.DoesNotExist: # pragma: no cover
pass
labeldict = {
int(w.id): w.__str__() for w in workouts
}
elif 'ids' in request.session and 'plottype' in request.session:
xparam = request.session['xparam']
yparam = request.session['yparam']
plottype = request.session['plottype']
teamid = 0
ids = request.session['ids']
workouts = []
for id in ids:
try:
workouts.append(Workout.objects.get(id=id))
except Workout.DoesNotExist: # pragma: no cover
pass
labeldict = {
int(w.id): w.__str__() for w in workouts
}
chartform = ChartParamChoiceForm(
initial = {
'xparam':xparam,
'yparam':yparam,
'plottype':plottype,
'teamid':teamid
}
)
else:
url = reverse('team_comparison_select',
kwargs={
'id':id,
'teamid':0})
return HttpResponseRedirect(url)
res = interactive_multiple_compare_chart(ids,xparam,yparam,
promember=promember,
plottype=plottype,
labeldict=labeldict)
script = res[0]
div = res[1]
errormessage = res[3]
if errormessage != '': # pragma: no cover
messages.error(request,errormessage)
r = getrower(request.user)
breadcrumbs = [
{
'url':'/rowers/list-workouts/',
'name':'Workouts'
},
{
'url':reverse('team_comparison_select',kwargs={'teamid':teamid}),
'name': 'Compare Select'
},
{
'url':reverse('multi_compare_view'),
'name': 'Comparison Chart'
}
]
if 'ps' in request.session: # pragma: no cover
ps = PlannedSession.objects.get(id=int(request.session['ps']))
breadcrumbs = [
{
'url': reverse('plannedsessions_view',
kwargs={'userid':userid}),
'name': 'Sessions'
},
{
'url':reverse('plannedsession_view',
kwargs={
'userid':userid,
'id':ps.id,
}
),
'name': ps.id
},
{
'url':reverse('plannedsession_compare_view',
kwargs={
'userid':userid,
'id':ps.id,
}
),
'name': 'Compare'
}
]
return render(request,'multicompare.html',
{'interactiveplot':script,
'the_div':div,
'breadcrumbs':breadcrumbs,
'rower':r,
'active':'nav-workouts',
'promember':promember,
'teamid':teamid,
'chartform':chartform,
'teams':get_my_teams(request.user),
})
# List Workouts
@login_required()