diff --git a/requirements.txt b/requirements.txt
index c09261fd..bfd9f646 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,6 +12,8 @@ billiard==3.6.0.0
bleach==3.1.0
bokeh==2.2.3
boto==2.49.0
+boto3==1.17.12
+botocore==1.20.12
bottle==0.12.18
braintree==3.55.0
cairocffi==1.0.2
@@ -55,11 +57,12 @@ django-rest-framework==0.1.0
django-rest-swagger==2.2.0
django-rq==1.3.1
django-rq-dashboard==0.3.3
-django-ses==0.8.10
+django-ses==1.0.3
django-shell-plus==1.1.7
django-social-share==1.3.2
django-suit==0.2.28
django-suit-rq==1.0.1
+django-taggit==1.3.0
django-tz-detect==0.2.9
djangorestframework==3.9.2
docopt==0.6.2
@@ -100,6 +103,7 @@ itypes==1.1.0
jedi==0.13.3
jeepney==0.4
Jinja2==2.10
+jmespath==0.10.0
json5==0.8.5
jsonschema==3.0.1
jupyter==1.0.0
@@ -180,10 +184,11 @@ ratelim==0.1.6
redis==3.5.3
requests==2.23.0
requests-oauthlib==1.2.0
-rowingdata==3.1.3
+rowingdata==3.1.4
rowingphysics==0.5.0
rq==0.13.0
rules==2.1
+s3transfer==0.3.4
scipy==1.5.4
SecretStorage==3.1.1
Send2Trash==1.5.0
diff --git a/rowers/models.py b/rowers/models.py
index bf9837b7..78f15530 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -44,6 +44,7 @@ import pandas as pd
from dateutil import parser
import datetime
+from taggit.managers import TaggableManager
#from rules.contrib.models import RulesModel
@@ -2291,6 +2292,8 @@ class PlannedSession(models.Model):
interval_string = models.TextField(max_length=1000,default=None,blank=True,null=True,
verbose_name='Interval String (optional)')
+ tags = TaggableManager()
+
def __str__(self):
name = self.name
@@ -2611,7 +2614,8 @@ class PlannedSessionTemplateForm(ModelForm):
'course',
'comment',
'interval_string',
- 'fitfile'
+ 'fitfile',
+ 'tags',
]
dateTimeOptions = {
diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html
index 03c89c2b..12150426 100644
--- a/rowers/templates/plannedsessioncreate.html
+++ b/rowers/templates/plannedsessioncreate.html
@@ -102,6 +102,17 @@
Click on session name to clone to current period
+ {% if alltags %}
+
+ Click on a tag to filter:
+ {% for tag in alltags %}
+ {{ tag }}
+ {% endfor %}
+
+
+ Clear tags
+
+ {% endif %}
diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py
index 95d2a01d..622cbb5f 100644
--- a/rowers/views/planviews.py
+++ b/rowers/views/planviews.py
@@ -7,6 +7,8 @@ from rowers.views.statements import *
from rowingdata import trainingparser
import json
+from taggit.models import Tag
+
@login_required
@permission_required('plannedsession.view_session',fn=get_session_by_pk,raise_exception=True)
def plannedsession_comment_view(request,id=0,userid=0):
@@ -54,8 +56,8 @@ def plannedsession_comment_view(request,id=0,userid=0):
res = myqueue(queuehigh,
handle_sendemailnewcomment,r.user.first_name,
- r.user.last_name,
- r.user.email,
+ r.user.last_name,
+ r.user.email,
request.user.first_name,
request.user.last_name,
comment,ps.name,ps.id,
@@ -93,7 +95,7 @@ def plannedsession_comment_view(request,id=0,userid=0):
handle_sendemailnewresponse,
u.first_name,
u.last_name,
- u.email,
+ u.email,
request.user.first_name,
request.user.last_name,
comment,
@@ -254,7 +256,7 @@ def plannedsession_message_view(request,id=0,userid=0):
'rower':r,
'breadcrumbs':breadcrumbs,
'active':active,
- 'userform':userform,
+ 'userform':userform,
})
@@ -463,7 +465,7 @@ def plannedsession_create_view(request,
sessionmode=sessionmode,
sessionvalue=sessionvalue,
sessionunit=sessionunit,
- sessionsport=sessionsport,
+ sessionsport=sessionsport,
comment=comment,
criterium=criterium,
interval_string=interval_string,
@@ -542,6 +544,8 @@ def plannedsession_create_view(request,
if request.GET.get('startdate') or request.GET.get('when'):
startdate, enddate = get_dates_timeperiod(request)
+
+
sps = get_sessions(r,startdate=startdate,enddate=enddate).exclude(
sessiontype='race')
@@ -549,6 +553,13 @@ def plannedsession_create_view(request,
manager=request.user,
is_template=True).order_by("name")
+ tag = request.GET.get('tag')
+ if tag:
+ tags = [tag]
+ sessiontemplates = sessiontemplates.filter(tags__name__in=tags).distinct()
+
+ alltags = Tag.objects.all()
+
try:
trainingplan = TrainingPlan.objects.filter(
startdate__lte = startdate,
@@ -575,6 +586,7 @@ def plannedsession_create_view(request,
'sessiontemplates':sessiontemplates,
'rower':r,
'timeperiod':timeperiod,
+ 'alltags':alltags,
})
@user_passes_test(can_plan,login_url="/rowers/paidplans/",
@@ -784,7 +796,7 @@ def plannedsession_teamcreate_view(request,
preferreddate=preferreddate,
sessiontype=sessiontype,
sessionmode=sessionmode,
- sessionsport=sessionsport,
+ sessionsport=sessionsport,
sessionvalue=sessionvalue,
sessionunit=sessionunit,
comment=comment,
@@ -1687,7 +1699,10 @@ def plannedsession_templateedit_view(request,id=0):
elif cd['sessionunit'] in ['km','m']:
cd['sessionmode'] = 'distance'
+ obj = sessioncreateform.save()
+
res, message = update_plannedsession(ps,cd)
+ #sessioncreateform.save_m2m()
if res:
messages.info(request,message)
@@ -1913,7 +1928,7 @@ def plannedsession_view(request,id=0,userid=0):
ps = get_object_or_404(PlannedSession,pk=id)
if ps.steps_json is not None:
- jsons = json.loads(ps.steps_json)
+ jsons = json.loads(ps.steps_json)
else:
jsons = {}
@@ -1921,8 +1936,8 @@ def plannedsession_view(request,id=0,userid=0):
try:
r = VirtualRace.objects.get(id=ps.id)
url = reverse('virtualevent_view',
- kwargs={'id':ps.id}
- )
+ kwargs={'id':ps.id}
+ )
return HttpResponseRedirect(url)
except VirtualRace.DoesNotExist:
pass
@@ -2004,8 +2019,8 @@ def plannedsession_view(request,id=0,userid=0):
job = myqueue(queue,handle_check_race_course,
w.csvfilename,w.id,ps.course.id,
record.id,
- w.user.user.email,w.user.user.first_name,
- mode='coursetest')
+ w.user.user.email,w.user.user.first_name,
+ mode='coursetest')
intsecs = 0
microsecs = 0
@@ -2030,30 +2045,30 @@ def plannedsession_view(request,id=0,userid=0):
userid = record.userid
uu = User.objects.get(id=userid)
try:
- w = Workout.objects.get(id=record.workoutid)
- wdict = {
- 'name': uu.first_name+' '+uu.last_name,
- 'date': w.date,
- 'distance': record.distance,
- 'type': w.workouttype,
+ w = Workout.objects.get(id=record.workoutid)
+ wdict = {
+ 'name': uu.first_name+' '+uu.last_name,
+ 'date': w.date,
+ 'distance': record.distance,
+ 'type': w.workouttype,
'workoutid':w.id,
- 'coursecompleted':True,
+ 'coursecompleted':True,
'sessionresult':record.id
- }
+ }
- coursecompleted = record.coursecompleted
- t = record.duration
- wdict['time'] = datetime.timedelta(
- hours=t.hour,
- seconds=t.second,
- minutes=t.minute,
- microseconds=t.microsecond
- )
+ coursecompleted = record.coursecompleted
+ t = record.duration
+ wdict['time'] = datetime.timedelta(
+ hours=t.hour,
+ seconds=t.second,
+ minutes=t.minute,
+ microseconds=t.microsecond
+ )
- wdict['coursecompleted'] = coursecompleted
+ wdict['coursecompleted'] = coursecompleted
- ranking.append(wdict)
+ ranking.append(wdict)
except Workout.DoesNotExist:
pass
@@ -2299,7 +2314,7 @@ def rower_create_trainingplan(request,id=0):
manager=themanager,
startdate=startdate,
enddate=enddate,status=status,
- notes=notes,
+ notes=notes,
)
p.save()
diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py
index 739391e0..9b18331b 100644
--- a/rowsandall_app/settings.py
+++ b/rowsandall_app/settings.py
@@ -79,6 +79,7 @@ INSTALLED_APPS = [
'django_social_share',
'django_countries',
'rules',
+ 'taggit',
]
AUTHENTICATION_BACKENDS = (
@@ -581,3 +582,5 @@ except KeyError:
RECAPTCHA_SITE_SECRET = ''
GEOIP_PATH = STATIC_ROOT
+
+TAGGIT_CASE_INSENSITIVE = True