Private
Public Access
1
0

adding rpe editing

This commit is contained in:
Sander Roosendaal
2022-11-25 17:14:19 +01:00
parent c324ee796a
commit b4973d8f52
8 changed files with 355 additions and 36 deletions

View File

@@ -28,6 +28,7 @@ from rowers.utils import landingpages
from rowers.metrics import axes, metricsgroups, rowingmetrics
from rowers.metrics import axlabels
from rowers.rower_rules import user_is_not_basic
from rowers import models
formaxlabels = axlabels.copy()
formaxlabels.pop('None')
@@ -401,7 +402,7 @@ class StandardsForm(forms.Form):
class DocumentsForm(forms.Form):
rpechoices = Workout.rpechoices
rpechoices = models.rpechoices
rpechoices = tuple([(-1, '---')]+list(rpechoices))
title = forms.CharField(required=False)
file = forms.FileField(required=False,

View File

@@ -3421,7 +3421,22 @@ class PlannedSessionFormSmall(ModelForm):
boattypes = mytypes.boattypes
# Workout
rpechoices = (
(0, 'Not Specified'),
(1, '1 Very Easy (a walk in the park)'), # 20 TSS / hour
(2, '2 Easy (You breathe normally, it feels comfortable)'), # 30 TSS / hour
(3, '3 Somewhat easy (You can talk easily but did you notice the beautiful clouds?)'),
# 50 TSS/hour
(4, '4 Moderate (You can talk in short spurts, breathing more labored, this feels just right)'),
(5, "5 (It's not that painful, you just don't want to be here all day.)"),
(6, '6 Somewhat Hard (You can say a few words if you need to)'), # 70 TSS / hour
(7, '7 Vigorous (This is starting to get painful)'),
# 100 TSS / hour
(8, "8 Hard (You can barely talk, breathing heavily, hoping you won't have to this that long)"),
(9, '9 Very Hard (My goodness, please make it stop)'), # 120 TSS / hour
# 140 TSS / hour
(10, '10 Max Effort (You can barely remember your name, you would rather rip out your toenails than go through this)')
)
class Workout(models.Model):
workouttypes = mytypes.workouttypes
@@ -3429,22 +3444,7 @@ class Workout(models.Model):
privacychoices = mytypes.privacychoices
adaptivetypes = mytypes.adaptivetypes
boatbrands = mytypes.boatbrands
rpechoices = (
(0, 'Not Specified'),
(1, '1 Very Easy (a walk in the park)'), # 20 TSS / hour
(2, '2 Easy (You breathe normally, it feels comfortable)'), # 30 TSS / hour
(3, '3 Somewhat easy (You can talk easily but did you notice the beautiful clouds?)'),
# 50 TSS/hour
(4, '4 Moderate (You can talk in short spurts, breathing more labored, this feels just right)'),
(5, "5 (It's not that painful, you just don't want to be here all day.)"),
(6, '6 Somewhat Hard (You can say a few words if you need to)'), # 70 TSS / hour
(7, '7 Vigorous (This is starting to get painful)'),
# 100 TSS / hour
(8, "8 Hard (You can barely talk, breathing heavily, hoping you won't have to this that long)"),
(9, '9 Very Hard (My goodness, please make it stop)'), # 120 TSS / hour
# 140 TSS / hour
(10, '10 Max Effort (You can barely remember your name, you would rather rip out your toenails than go through this)')
)
user = models.ForeignKey(Rower, on_delete=models.CASCADE)
team = models.ManyToManyField(Team, blank=True)
@@ -3586,6 +3586,10 @@ class Workout(models.Model):
return stri
class WorkoutRPEForm(ModelForm):
class Meta:
model = Workout
fields = ['rpe']
class TombStone(models.Model):
user = models.ForeignKey(Rower, on_delete=models.CASCADE)

View File

@@ -3187,7 +3187,8 @@ def df_from_summary(data):
@app.task
def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttimezone, debug=False, **kwargs):
def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec,
defaulttimezone, debug=False, **kwargs):
time.sleep(delaysec)
dologging('c2_import.log',str(c2id)+' for userid '+str(userid))
data = alldata[c2id]

View File

@@ -92,6 +92,11 @@
{% if workout.rankingpiece %}
<span style="font-size: smaller"><i class="fal fa-asterisk"></i></span>
{% endif %}
{% if workout.rpe == 0 %}
<span style="font-size: smaller">
<a href="/rowers/workout/{{ workout.id|encode }}/edit/">No RPE</a>
</span>
{% endif %}
<div>
{% if workout.name != '' %}
<h3>

View File

@@ -0,0 +1,209 @@
{% extends "newbase.html" %}
{% load static %}
{% load rowerfilters %}
{% block title %}Rowsandall Workouts List{% endblock %}
{% block scripts %}
<script>
setTimeout("location.reload(true);",180000);
</script>
<script
type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
</script>
{% endblock %}
{% block main %}
<style>
#mypointer {
cursor: pointer;
}
div.columns { width: 100%; }
div.columns div { width: 20%; padding: 10px; float: left; }
div.icondiv svg { height: 35px; }
</style>
<h1>
Workouts of {{ rower.user.first_name }} {{ rower.user.last_name }}
</h1>
<ul class="main-content">
<li class="grid_4">
<span>
{% if workouts.has_previous %}
{% if request.GET.q %}
<a href="?page=1&q={{ request.GET.q }}">
<i class="fas fa-arrow-alt-to-left"></i>
</a>
<a
href="?page={{ workouts.previous_page_number }}&q={{ request.GET.q }}&when={{ timeperiod }}">
<i class="fas fa-arrow-alt-left"></i>
</a>
{% else %}
<a href="?page=1&when={{ timeperiod }}">
<i class="fas fa-arrow-alt-to-left"></i>
</a>
<a href="?page={{ workouts.previous_page_number }}&when={{ timeperiod }}">
<i class="fas fa-arrow-alt-left"></i>
</a>
{% endif %}
{% endif %}
</span>
</li>
<li class="grid_4">
<form method="post" target="">
{% csrf_token %}
{{ rpe_formset.management_form }}
<table width="100%">
<thead>
<tr>
<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
{% for field in rpe_formset.0.visible_fields %}
<td>{{ field.label_tag }}</td>
{% endfor %}
</tr>
</thead>
<tbody>
{% for form in rpe_formset %}
<tr class="session_form_row">
<td>
{{ form.id }}
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
</td>
<td>
{% if form.instance.pk %}{{ form.instance.startdatetime }}{% endif %}
</td>
<td>
{% if form.instance.pk %}{{ form.instance.name }}{% endif %}
</td>
{% if form.instance.pk %}
{% for field in form.visible_fields %}
<td>
{{ field }}
</td>
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit">Submit</button>
</form>
</li>
{% if workouts %}
{% for workout in workouts %}
<li class="grid_4 divlines">
{{ workout.date|date:"Y-m-d" }} {{ workout.starttime|date:"H:i" }}
{% if workout.duplicate %}
<span style="font-size: smaller"><i class="fal fa-angle-double-up"></i></span>
{% endif %}
{% if workout.rankingpiece %}
<span style="font-size: smaller"><i class="fal fa-asterisk"></i></span>
{% endif %}
{% if workout.rpe == 0 %}
<span style="font-size: smaller">
<a href="/rowers/workout/{{ workout.id|encode }}/edit/">No RPE</a>
</span>
{% endif %}
<div>
{% if workout.name != '' %}
<h3>
{% if team %}
<a
href={% url rower.defaultlandingpage3 id=workout.id|encode %}
title="{{ rower.defaultlandingpage3|verbose }}">
{{ workout.name }} ({{ workout.user.user.first_name }} {{ workout.user.user.last_name}})
</a>
{% else %}
<a
href={% url rower.defaultlandingpage3 id=workout.id|encode %}
title="{{ rower.defaultlandingpage3|verbose }}">
{{ workout.name }}
</a>
{% endif %}
</h3>
{% else %}
<h3>
{% if team %}
<a
href={% url rower.defaultlandingpage id=workout.id|encode %}
title="{{ rower.defaultlandingpage|verbose }}">
No Name ({{ workout.user.user.first_name }} {{ workout.user.user.last_name}})
</a>
{% else %}
<a
href={% url rower.defaultlandingpage id=workout.id|encode %}
title="{{ rower.defaultlandingpage|verbose }}">
No Name
</a>
{% endif %}
</h3>
{% endif %}
</div>
<div class="workoutcontainer">
<div class="icondiv">
{% with workout.workouttype|icon|safe as templateName %}
{% include templateName %}
{% endwith %}
</div>
<div class="workoutelement">
<span style="color:#555">Distance</span><br>
{{ workout.distance|distanceprint }}
</div>
<div class="workoutelement">
<span style="color:#555">Time</span><br>
{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
</div>
<div class="workoutelement">
{% if workout|may_edit:request %}
<a class="small"
href={% url rower.defaultlandingpage id=workout.id|encode %}
title="{{ rower.defaultlandingpage|verbose }}">
<i class="{{ rower.defaultlandingpage|landingicon }}"></i></a>
{% else %}
&nbsp;
{% endif %}
</div>
<div class="workoutelement">
{% if workout|may_edit:request %}
{% if rower.defaultlandingpage2 != 'workout_delete' %}
<a class="small"
href={% url rower.defaultlandingpage2 id=workout.id|encode %}
title="{{ rower.defaultlandingpage2|verbose }}">
<i class="{{ rower.defaultlandingpage2|landingicon }}"></i></a>
{% else %}
<a class="small"
href={% url rower.defaultlandingpage2 id=workout.id|encode %}
title="{{ rower.defaultlandingpage2|verbose }}">
<i class="{{ rower.defaultlandingpage2|landingicon }}"></i></a>
{% endif %}
{% else %}
&nbsp;
{% endif %}
</div>
</div>
</li>
{% endfor %}
{% else %}
<li> No workouts found </li>
{% endif %}
</ul>
{% endblock %}
{% block sidebar %}
{% include 'menu_workouts.html' %}
{% endblock %}

View File

@@ -286,6 +286,8 @@ urlpatterns = [
views.agegrouprecordview, name='agegrouprecordview'),
re_path(r'^agegrouprecords/$',
views.agegrouprecordview, name='agegrouprecordview'),
re_path(r'^workouts/setrpe/$', views.workouts_setrpe_view,
name='workouts_setrpe_view'),
re_path(r'^list-workouts/team/(?P<teamid>\d+)/$', views.workouts_view,
name='workouts_view'),
re_path(r'^(?P<rowerid>\d+)/list-workouts/$', views.workouts_view,

View File

@@ -159,22 +159,20 @@ from rowers.models import (
VirtualRaceFollower, TombStone, InstantPlan,
PlannedSessionStep,InStrokeAnalysis, ForceCurveAnalysis
)
from rowers.models import (
RowerPowerForm, RowerHRZonesForm, RowerForm, RowerCPForm, GraphImage, AdvancedWorkoutForm,
RowerPowerZonesForm, AccountRowerForm, UserForm,
Team, TeamForm, TeamInviteForm, TeamInvite, TeamRequest,
WorkoutComment, WorkoutCommentForm, RowerExportForm,
CalcAgePerformance,
PowerTimeFitnessMetric, BlogPost,
PlannedSessionForm, PlannedSessionTemplateForm,
PlannedSessionFormSmall, GeoCourseEditForm, VirtualRace,
VirtualRaceForm, VirtualRaceResultForm, RowerImportExportForm,
IndoorVirtualRaceResultForm, IndoorVirtualRaceResult,
IndoorVirtualRaceForm, PlannedSessionCommentForm,
Alert, Condition, StaticChartRowerForm,
FollowerForm, VirtualRaceAthleteForm, InstantPlanForm, DataRowerForm,
StepEditorForm,
)
from rowers.models import ( RowerPowerForm, RowerHRZonesForm,
RowerForm, RowerCPForm, GraphImage, AdvancedWorkoutForm,
RowerPowerZonesForm, AccountRowerForm, UserForm, Team, TeamForm,
TeamInviteForm, TeamInvite, TeamRequest, WorkoutComment,
WorkoutCommentForm, RowerExportForm, CalcAgePerformance,
PowerTimeFitnessMetric, BlogPost, PlannedSessionForm,
PlannedSessionTemplateForm, PlannedSessionFormSmall,
GeoCourseEditForm, VirtualRace, VirtualRaceForm,
VirtualRaceResultForm, RowerImportExportForm, WorkoutRPEForm,
IndoorVirtualRaceResultForm, IndoorVirtualRaceResult,
IndoorVirtualRaceForm, PlannedSessionCommentForm, Alert,
Condition, StaticChartRowerForm, FollowerForm,
VirtualRaceAthleteForm, InstantPlanForm, DataRowerForm,
StepEditorForm, )
from rowers.models import (
FavoriteForm, BaseFavoriteFormSet, SiteAnnouncement, BasePlannedSessionFormSet,
get_course_timezone, BaseConditionFormSet,

View File

@@ -1921,6 +1921,99 @@ def plannedsession_compare_view(request, id=0, userid=0):
return HttpResponseRedirect(url)
# set RPE for list of workouts
@login_required()
def workouts_setrpe_view(request):
startdate, enddate = get_dates_timeperiod(
request, defaulttimeperiod='lastyear')
r = getrequestrower(request)
startdate = datetime.datetime.combine(startdate, datetime.time())
enddate = datetime.datetime.combine(enddate, datetime.time(23, 59, 59))
workouts = Workout.objects.filter(
user=r,rpe=0,
startdatetime__gte=startdate,
startdatetime__lte=enddate
).order_by("-date", "-starttime")
dateform = DateRangeForm(initial={
'startdate': startdate,
'enddate': enddate,
})
WorkoutsRPEFormSet = modelformset_factory(
Workout,
form=WorkoutRPEForm,
)
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
rpe_formset = WorkoutsRPEFormSet(request.POST)
if dateform.is_valid(): # pragma: no cover
startdate = dateform.cleaned_data['startdate']
enddate = dateform.cleaned_data['enddate']
if rpe_formset.is_valid():
for item in rpe_formset.cleaned_data:
rpe = item['rpe']
workout = item['id']
if workout:
workout.rpe = rpe
workout.save()
workouts = Workout.objects.filter(
user=r,rpe=0,
startdatetime__gte=startdate,
startdatetime__lte=enddate
).order_by("-date", "-starttime")
rpe_formset = WorkoutsRPEFormSet(queryset=workouts)
usertimezone = pytz.timezone(r.defaulttimezone)
startdate = datetime.datetime.combine(
startdate, datetime.time()).astimezone(usertimezone)
enddate = datetime.datetime.combine(
enddate, datetime.time(23, 59, 59)).astimezone(usertimezone)
if enddate < startdate: # pragma: no cover
s = enddate
enddate = startdate
startdate = s
today = timezone.now()
announcements = SiteAnnouncement.objects.filter(
expires__gte=today
).order_by(
"-created",
"-id"
)
breadcrumbs = [
{
'url': '/rowers/list-workouts/',
'name': 'Workouts'
},
{
'url': '/rowers/workouts/setrpe/',
'name': 'Set RPE'
}
]
return render(request,'workouts_rpe.html',
{
'workouts': workouts,
'active': 'nav-workouts',
'rower': r,
'breadcrumbs': breadcrumbs,
'dateform': dateform,
'startdate': startdate,
'enddate': enddate,
'rpe_formset': rpe_formset,
})
# List Workouts
@login_required()
@@ -2111,6 +2204,12 @@ def workouts_view(request, message='', successmessage='',
]
timeperiod = startdate.strftime(
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
norpecount = len([w for w in workouts if w.rpe==0])
if norpecount:
messages.info(request,'You have workouts with no RPE value set. \
Click <a href="/rowers/workouts/setrpe">here</a> to update them.')
return render(request, 'list_workouts.html',
{'workouts': workouts,
'active': 'nav-workouts',