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,14 +3421,6 @@ class PlannedSessionFormSmall(ModelForm):
boattypes = mytypes.boattypes
# Workout
class Workout(models.Model):
workouttypes = mytypes.workouttypes
workoutsources = mytypes.workoutsources
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
@@ -3446,6 +3438,14 @@ class Workout(models.Model):
(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
workoutsources = mytypes.workoutsources
privacychoices = mytypes.privacychoices
adaptivetypes = mytypes.adaptivetypes
boatbrands = mytypes.boatbrands
user = models.ForeignKey(Rower, on_delete=models.CASCADE)
team = models.ManyToManyField(Team, blank=True)
plannedsession = models.ForeignKey(PlannedSession, blank=True, null=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,
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,
)
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',