Private
Public Access
1
0

Merge branch 'feature/warmingups' into develop

This commit is contained in:
2025-02-18 15:41:20 +01:00
7 changed files with 162 additions and 12 deletions
+17 -5
View File
@@ -203,20 +203,32 @@ class IntervalsIntegration(SyncIntegration):
return 0 return 0
id = response.json()['id'] id = response.json()['id']
workout.uploadedtointervals = id
workout.save()
os.remove(filename)
# set workout type to workouttype # set workout type to workouttype
url = "https://intervals.icu/api/v1/activity/{activityid}".format(activityid=id) url = "https://intervals.icu/api/v1/activity/{activityid}".format(activityid=id)
thetype = mytypes.intervalsmapping[workout.workouttype] thetype = mytypes.intervalsmapping[workout.workouttype]
response = requests.put(url, headers=headers, json={'type': thetype}) jsondict = {'type': thetype}
subtype = w.sub_type
if subtype:
jsondict['sub_type'] = subtype
jsondict['icu_rpe'] = workout.rpe
jsondict['commute'] = workout.is_commute
if workout.plannedsession:
jsondict['paired_event_id'] = workout.plannedsession.intervals_icu_id
response = requests.put(url, headers=headers, json=jsondict)
if response.status_code not in [200, 201]: if response.status_code not in [200, 201]:
return 0 return 0
workout.uploadedtointervals = id
workout.save()
os.remove(filename)
dologging('intervals.icu.log', "Exported workout {id}".format(id=workout.id)) dologging('intervals.icu.log', "Exported workout {id}".format(id=workout.id))
+15
View File
@@ -1271,6 +1271,8 @@ class Rower(models.Model):
imports_are_private = models.BooleanField(default=False, verbose_name='Make imports private by default') imports_are_private = models.BooleanField(default=False, verbose_name='Make imports private by default')
show_commutes = models.BooleanField(default=False, verbose_name='Show commutes in workout list') show_commutes = models.BooleanField(default=False, verbose_name='Show commutes in workout list')
small_commutes = models.BooleanField(default=False, verbose_name='Show commutes on a single line in workout list') small_commutes = models.BooleanField(default=False, verbose_name='Show commutes on a single line in workout list')
show_wups_cds = models.BooleanField(default=False, verbose_name='Show warmups and cooldowns in workout list')
small_wups_cds = models.BooleanField(default=False, verbose_name='Show warmups and cooldowns on a single line in workout list')
# Friends/Team # Friends/Team
friends = models.ManyToManyField("self", blank=True) friends = models.ManyToManyField("self", blank=True)
@@ -3718,6 +3720,13 @@ rpechoices = (
(10, '10 Max Effort (You can barely remember your name, you would rather rip out your toenails than go through this)') (10, '10 Max Effort (You can barely remember your name, you would rather rip out your toenails than go through this)')
) )
subcategories = (
(None, "None"),
("Race", "Race"),
("Commute", "Commute"),
("Warming Up", "Warming Up"),
("Cooling Down", "Cooling Down")
)
class Workout(models.Model): class Workout(models.Model):
workouttypes = mytypes.workouttypes workouttypes = mytypes.workouttypes
@@ -3770,6 +3779,8 @@ class Workout(models.Model):
verbose_name='Rate of Perceived Exertion') verbose_name='Rate of Perceived Exertion')
is_commute = models.BooleanField(default=False) is_commute = models.BooleanField(default=False)
is_race = models.BooleanField(default=False)
sub_type = models.CharField(default=None, null=True, blank=True, choices=subcategories, max_length=250)
weightcategory = models.CharField( weightcategory = models.CharField(
default="hwt", default="hwt",
@@ -4624,6 +4635,7 @@ class WorkoutForm(ModelForm):
'duration', 'duration',
'distance', 'distance',
'workouttype', 'workouttype',
'sub_type',
'boattype', 'boattype',
'boatname', 'boatname',
'seatnumber', 'seatnumber',
@@ -4636,6 +4648,7 @@ class WorkoutForm(ModelForm):
'rankingpiece', 'rankingpiece',
'duplicate', 'duplicate',
'is_commute', 'is_commute',
'is_race',
'plannedsession'] 'plannedsession']
widgets = { widgets = {
'date': AdminDateWidget(), 'date': AdminDateWidget(),
@@ -5206,6 +5219,8 @@ class AccountRowerForm(ModelForm):
'defaultlandingpage3', 'defaultlandingpage3',
'show_commutes', 'show_commutes',
'small_commutes', 'small_commutes',
'show_wups_cds',
'small_wups_cds',
'offercoaching', 'autojoin', 'emailalternatives'] 'offercoaching', 'autojoin', 'emailalternatives']
widgets = { widgets = {
+23
View File
@@ -3599,6 +3599,7 @@ def handle_intervals_getworkout(rower, intervalstoken, workoutid, debug=False, *
return 0 return 0
data = response.json() data = response.json()
try: try:
title = data['name'] title = data['name']
except KeyError: except KeyError:
@@ -3621,6 +3622,21 @@ def handle_intervals_getworkout(rower, intervalstoken, workoutid, debug=False, *
except KeyError: except KeyError:
is_commute = False is_commute = False
try:
subtype = data['sub_type']
if subtype is not None:
subtype = subtype.capitalize()
except KeyError:
subtype = None
try:
is_race = data['race']
if is_race is None:
is_race = False
except KeyError:
is_race = False
url = "https://intervals.icu/api/v1/activity/{workoutid}/fit-file".format(workoutid=workoutid) url = "https://intervals.icu/api/v1/activity/{workoutid}/fit-file".format(workoutid=workoutid)
response = requests.get(url, headers=headers) response = requests.get(url, headers=headers)
@@ -3667,6 +3683,13 @@ def handle_intervals_getworkout(rower, intervalstoken, workoutid, debug=False, *
if is_commute: if is_commute:
for w in ws: for w in ws:
w.is_commute = True w.is_commute = True
w.sub_type = "Commute"
w.save()
for w in ws:
w.sub_type = subtype
w.save()
if is_race:
w.is_race = True
w.save() w.save()
if ws.count() > 0: if ws.count() > 0:
pss = PlannedSession.objects.filter(rower=rower,intervals_icu_id=paired_event_id) pss = PlannedSession.objects.filter(rower=rower,intervals_icu_id=paired_event_id)
+66 -4
View File
@@ -34,12 +34,18 @@
</h1> </h1>
{% endif %} {% endif %}
{% if nr_commutes %} {% if nr_commutes or nr_wups_cds %}
<p> <p>
<a href="?show_commutes=true">Show {{ nr_commutes }} commutes</a> {% if nr_commutes %}
<a href="?show_commutes=true">Show {{ nr_commutes }} commutes</a>&nbsp;
{% endif %}
{% if nr_wups_cds %}
<a href="?show_wups_cds=true">Show {{ nr_wups_cds }} warmups and cooldowns</a>
{% endif %}
</p> </p>
{% endif %} {% endif %}
<ul class="main-content"> <ul class="main-content">
<li class="grid_4"> <li class="grid_4">
<span> <span>
@@ -109,7 +115,7 @@
{% endif %} {% endif %}
{% for workout in workouts %} {% for workout in workouts %}
{% if not workout.is_commute or not user.rower.small_commutes %} {% if workout|show_normal %}
<li class="grid_4 divlines"> <li class="grid_4 divlines">
{% if request.GET.selectworkouts %} {% if request.GET.selectworkouts %}
<input type="checkbox" id="workoutid" value={{ workout.id|encode }} name="workoutid" /> <input type="checkbox" id="workoutid" value={{ workout.id|encode }} name="workoutid" />
@@ -124,6 +130,14 @@
{% if workout.rankingpiece %} {% if workout.rankingpiece %}
<span style="font-size: smaller"><i class="fal fa-asterisk"></i></span> <span style="font-size: smaller"><i class="fal fa-asterisk"></i></span>
{% endif %} {% endif %}
{% if workout.is_commute %}
Commute
{% endif %}
{% if workout.sub_type == "Warming Up" %}
Warming Up
{% elif workout.sub_type == "Cooling Down" %}
Cooling Down
{% endif %}
{% if workout.rpe == 0 and not workout.duplicate %} {% if workout.rpe == 0 and not workout.duplicate %}
<span style="font-size: smaller"> <span style="font-size: smaller">
<a href="/rowers/workout/{{ workout.id|encode }}/edit/">No RPE</a> <a href="/rowers/workout/{{ workout.id|encode }}/edit/">No RPE</a>
@@ -207,7 +221,7 @@
</div> </div>
</div> </div>
</li> </li>
{% elif show_commutes and user.rower.small_commutes %} {% elif workout|show_commute %}
<li class="grid_4 divlines"> <li class="grid_4 divlines">
<div class="workoutcontainer"> <div class="workoutcontainer">
<div class="workoutelement"> <div class="workoutelement">
@@ -251,6 +265,54 @@
</div> </div>
</div> </div>
</li> </li>
{% elif workout|show_wup_cd %}
<li class="grid_4 divlines">
<div class="workoutcontainer">
<div class="workoutelement">
{% if workout.sub_type == "Warming Up" %}
<span style="font-size: smaller"><i class="fa-solid fa-temperature-arrow-up"></i></span>
{% else %}
<span style="font-size: smaller"><i class="fa-solid fa-temperature-arrow-down"></i></span>
{% endif %}
</div>
<div class="workoutelement">
<span style="color:#555">Distance</span>
{{ workout.distance|distanceprint }}
</div>
<div class="workoutelement">
<span style="color:#555">Time</span>
{{ 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>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
+19
View File
@@ -48,6 +48,25 @@ from six import string_types
register = template.Library() register = template.Library()
@register.filter
def show_normal(workout):
# is commute
hide_commute = workout.is_commute and (workout.user.small_commutes or not workout.user.show_commutes)
hide_warmup = workout.sub_type in ["Warming Up", "Cooling Down"] and (workout.user.small_wups_cds or not workout.user.show_wups_cds)
return not hide_commute and not hide_warmup
@register.filter
def show_commute(workout):
return workout.is_commute and workout.user.small_commutes
@register.filter
def show_wup_cd(workout):
return workout.sub_type in ["Warming Up", "Cooling Down"] and workout.user.small_wups_cds
@register.filter
def is_wup_cd(workout):
return workout.sub_type in ["Warm Up", "Cooling Down"]
@register.filter @register.filter
def getworkoutname(id): def getworkoutname(id):
try: try:
Binary file not shown.
+19
View File
@@ -2080,10 +2080,12 @@ def workouts_bulk_actions(request):
elif action == 'set commute': elif action == 'set commute':
for w in workouts: for w in workouts:
w.is_commute = True w.is_commute = True
w.sub_type = "Commute"
w.save() w.save()
elif action == 'unset commute': elif action == 'unset commute':
for w in workouts: for w in workouts:
w.is_commute = False w.is_commute = False
w.sub_type = None
w.save() w.save()
elif action == 'set public': elif action == 'set public':
for w in workouts: for w in workouts:
@@ -2155,6 +2157,8 @@ def workouts_view(request, message='', successmessage='',
if show_commutes == 'true': if show_commutes == 'true':
show_commutes = True show_commutes = True
show_wups_cds = request.GET.get('show_wups_cds', False)
# check if access is allowed # check if access is allowed
startdate = datetime.datetime.combine(startdate, datetime.time()) startdate = datetime.datetime.combine(startdate, datetime.time())
@@ -2280,6 +2284,11 @@ def workouts_view(request, message='', successmessage='',
nr_commutes = workouts.filter(is_commute=True).count() nr_commutes = workouts.filter(is_commute=True).count()
workouts = workouts.exclude(is_commute=True) workouts = workouts.exclude(is_commute=True)
nr_wups_cds = 0
show_wups_cds = show_wups_cds or r.show_wups_cds
if not show_wups_cds:
nr_wups_cds = workouts.filter(sub_type__in=['Warming Up', 'Cooling Down']).count()
workouts = workouts.exclude(sub_type='Warming Up').exclude(sub_type='Cooling Down')
workoutsnohr = workouts.exclude(averagehr__isnull=False) workoutsnohr = workouts.exclude(averagehr__isnull=False)
for w in workoutsnohr: # pragma: no cover for w in workoutsnohr: # pragma: no cover
@@ -2373,6 +2382,8 @@ def workouts_view(request, message='', successmessage='',
'totalhours': totalhours, 'totalhours': totalhours,
'nr_commutes': nr_commutes, 'nr_commutes': nr_commutes,
'show_commutes': show_commutes, 'show_commutes': show_commutes,
'show_wups_cds': show_wups_cds,
'nr_wups_cds': nr_wups_cds,
}) })
@@ -4503,6 +4514,8 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
newdragfactor = form.cleaned_data['dragfactor'] newdragfactor = form.cleaned_data['dragfactor']
thetimezone = form.cleaned_data['timezone'] thetimezone = form.cleaned_data['timezone']
is_commute = form.cleaned_data['is_commute'] is_commute = form.cleaned_data['is_commute']
is_race = form.cleaned_data['is_race']
subtype = form.cleaned_data['sub_type']
try: try:
rpe = form.cleaned_data['rpe'] rpe = form.cleaned_data['rpe']
if not rpe: # pragma: no cover if not rpe: # pragma: no cover
@@ -4524,6 +4537,10 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
boatname = form.cleaned_data.get('boatname', '') boatname = form.cleaned_data.get('boatname', '')
empowerside = form.cleaned_data.get('empowerside','port') empowerside = form.cleaned_data.get('empowerside','port')
if is_race and subtype is None:
subtype = "Race"
elif is_commute and subtype is None:
subtype = "Commute"
if private: if private:
privacy = 'hidden' privacy = 'hidden'
@@ -4581,6 +4598,8 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
row.empowerside = empowerside row.empowerside = empowerside
row.seatnumber = seatnumber row.seatnumber = seatnumber
row.is_commute = is_commute row.is_commute = is_commute
row.is_race = is_race
row.sub_type = subtype
dragchanged = False dragchanged = False
if newdragfactor != row.dragfactor: # pragma: no cover if newdragfactor != row.dragfactor: # pragma: no cover