list of intervals
This commit is contained in:
@@ -63,7 +63,7 @@ class IntervalsIntegration(SyncIntegration):
|
|||||||
'base_url': 'https://intervals.icu/api/v1/',
|
'base_url': 'https://intervals.icu/api/v1/',
|
||||||
'grant_type': 'refresh_token',
|
'grant_type': 'refresh_token',
|
||||||
'headers': headers,
|
'headers': headers,
|
||||||
'scope': 'ACTIVITY:WRITE, LIBRARY:READ',
|
'scope': 'ACTIVITY:WRITE, LIBRARY:READ, CALENDAR:WRITE',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_token(self, code, *args, **kwargs):
|
def get_token(self, code, *args, **kwargs):
|
||||||
@@ -297,5 +297,48 @@ class IntervalsIntegration(SyncIntegration):
|
|||||||
def token_refresh(self, *args, **kwargs):
|
def token_refresh(self, *args, **kwargs):
|
||||||
return super(IntervalsIntegration, self).token_refresh(*args, **kwargs)
|
return super(IntervalsIntegration, self).token_refresh(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_plannedsessions_list(self, *args, **kwargs):
|
||||||
|
_ = self.open()
|
||||||
|
r = self.rower
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Authorization': 'Bearer ' + r.intervals_token,
|
||||||
|
}
|
||||||
|
|
||||||
|
# first get the folders - we need the folder id for the next call
|
||||||
|
url = self.oauth_data['base_url'] + 'athlete/0/folders'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code != 200:
|
||||||
|
return []
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
# get all elements in the list where start_date_local is not None
|
||||||
|
folders = [x for x in data if x['start_date_local']]
|
||||||
|
for plan in folders:
|
||||||
|
plan_start_date = arrow.get(plan['start_date_local']).datetime
|
||||||
|
for session in plan["children"]:
|
||||||
|
session["date"] = (plan_start_date+timedelta(days=session["day"])).date()
|
||||||
|
|
||||||
|
return folders
|
||||||
|
|
||||||
|
def get_plannedsession(self, id, *args, **kwargs):
|
||||||
|
_ = self.open()
|
||||||
|
r = self.rower
|
||||||
|
|
||||||
|
url = self.oauth_data['base_url'] + 'athlete/0/workouts/' + str(id)
|
||||||
|
headers = {
|
||||||
|
'Authorization': 'Bearer ' + r.intervals_token,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
dologging('intervals.icu.log', response.text)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
47
rowers/templates/intervals_list_import.html
Normal file
47
rowers/templates/intervals_list_import.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}Sessions on intervals.icu{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<h1>Sessions on Intervals.icu</h1>
|
||||||
|
{% if folders %}
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_4">
|
||||||
|
<form enctype="multipart/form-data" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" name="action" value="Import selected sessions">
|
||||||
|
<table width="70%" class="listtable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Import</th>
|
||||||
|
<th>Plan</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Training Load</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for folder in folders %}
|
||||||
|
{% for session in folder.children %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="session" value="{{ session.id }}">
|
||||||
|
</td>
|
||||||
|
<td>{{ folder.name }}</td>
|
||||||
|
<td>{{ session.date }}</td>
|
||||||
|
<td>{{ session.description }}</td>
|
||||||
|
<td>{{ session.type }}</td>
|
||||||
|
<td>{{ session.icu_training_load }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
@@ -630,6 +630,8 @@ urlpatterns = [
|
|||||||
views.workout_undo_smoothenpace_view, name='workout_undo_smoothenpace_view'),
|
views.workout_undo_smoothenpace_view, name='workout_undo_smoothenpace_view'),
|
||||||
re_path(r'^session/rojaboimport/$', views.workout_rojaboimport_view,
|
re_path(r'^session/rojaboimport/$', views.workout_rojaboimport_view,
|
||||||
name='workout_rojaboimport_view'),
|
name='workout_rojaboimport_view'),
|
||||||
|
re_path(r'^session/intervalsimport/$', views.plannedsession_intervalsimport_view,
|
||||||
|
name='plannedsession_intervalsimport_view'),
|
||||||
re_path(r'^workout/(?P<source>\w+.*)import/$',
|
re_path(r'^workout/(?P<source>\w+.*)import/$',
|
||||||
views.workout_import_view, name='workout_import_view'),
|
views.workout_import_view, name='workout_import_view'),
|
||||||
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',
|
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',
|
||||||
|
|||||||
@@ -681,8 +681,51 @@ def rower_process_testcallback(request): # pragma: no cover
|
|||||||
return HttpResponse(text)
|
return HttpResponse(text)
|
||||||
|
|
||||||
|
|
||||||
|
# view to list planned sessions from intervals.icu
|
||||||
|
@login_required()
|
||||||
|
@user_passes_test(isplanmember, login_url="/rowers/paidplans/",
|
||||||
|
message="This functionality requires a Self-coach plan or higher",
|
||||||
|
redirect_field_name=None)
|
||||||
|
def plannedsession_intervalsimport_view(request, message="", userid=0):
|
||||||
|
r = getrequestrower(request, userid=userid)
|
||||||
|
if r.user != request.user:
|
||||||
|
messages.error(
|
||||||
|
request, 'You can only access your own workouts on Intervals.icu, not those of your athletes')
|
||||||
|
url = reverse('plannedsession_intervalsimport_view',
|
||||||
|
kwargs={'userid': request.user.id})
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
integration = importsources['intervals'](request.user)
|
||||||
|
sessions_list = integration.get_plannedsessions_list()
|
||||||
|
|
||||||
|
if request.method == 'POST': # pragma: no cover
|
||||||
|
try:
|
||||||
|
tdict = dict(request.POST.lists())
|
||||||
|
print(tdict)
|
||||||
|
ids = tdict['session']
|
||||||
|
sessionids = [int(id) for id in ids]
|
||||||
|
for sessionid in sessionids:
|
||||||
|
try:
|
||||||
|
_ = integration.get_plannedsession(sessionid)
|
||||||
|
except NoTokenError:
|
||||||
|
pass
|
||||||
|
messages.info(
|
||||||
|
request,
|
||||||
|
'Your Intervals.icu planned sessions will be imported in the background.'
|
||||||
|
' It may take a few minutes before they appear.')
|
||||||
|
url = reverse('plannedsessions_view')
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return render(request, 'intervals_list_import.html',
|
||||||
|
{
|
||||||
|
'folders': sessions_list,
|
||||||
|
'rower': r,
|
||||||
|
'active': 'nav-plans',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# The page where you select which Strava workout to import
|
|
||||||
@login_required()
|
@login_required()
|
||||||
@user_passes_test(isplanmember, login_url="/rowers/paidplans/",
|
@user_passes_test(isplanmember, login_url="/rowers/paidplans/",
|
||||||
message="This functionality requires a Self-coach plan or higher",
|
message="This functionality requires a Self-coach plan or higher",
|
||||||
|
|||||||
Reference in New Issue
Block a user