diff --git a/logos/bcsquare.png b/logos/bcsquare.png new file mode 100644 index 00000000..547f4488 Binary files /dev/null and b/logos/bcsquare.png differ diff --git a/logos/boatcoachlogo.png b/logos/boatcoachlogo.png new file mode 100644 index 00000000..057ad75f Binary files /dev/null and b/logos/boatcoachlogo.png differ diff --git a/logos/boatcoachlogo.xcf b/logos/boatcoachlogo.xcf new file mode 100644 index 00000000..52f41b8a Binary files /dev/null and b/logos/boatcoachlogo.xcf differ diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 4e24d3ef..b92692bb 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -63,12 +63,16 @@ class Command(BaseCommand): wid = [make_new_workout_from_email(rr,a.document,name)] res += wid link = 'http://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' - dd = send_confirm(u,name,link) except: # replace with code to process error res += ['fail: '+name] donotdelete = 1 + try: + dd = send_confirm(u,name,link) + except: + pass + except Rower.DoesNotExist: pass diff --git a/rowers/sporttracksstuff.py b/rowers/sporttracksstuff.py index 7783a8ca..b0270b03 100644 --- a/rowers/sporttracksstuff.py +++ b/rowers/sporttracksstuff.py @@ -181,8 +181,10 @@ def createsporttracksworkoutdata(w): maxhr = int(row.df[' HRCur (bpm)'].max()) # adding diff, trying to see if this is valid - t = row.df.ix[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)'] + #t = row.df.ix[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)'] + t = row.df.ix[:,'TimeStamp (sec)'].values-row.df.ix[0,'TimeStamp (sec)'] t[0] = t[1] + d = row.df.ix[:,'cum_dist'].values d[0] = d[1] t = t.astype(int) @@ -196,9 +198,12 @@ def createsporttracksworkoutdata(w): try: lat = row.df[' latitude'].values lon = row.df[' longitude'].values + if not lat.std() and not lon.std(): + haslatlon = 0 except KeyError: haslatlon = 0 + haspower = 1 try: power = row.df[' Power (watts)'].values diff --git a/rowers/templates/400.html b/rowers/templates/400.html index 735edfd4..caf15419 100644 --- a/rowers/templates/400.html +++ b/rowers/templates/400.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "bases.html" %} {% load staticfiles %} {% load rowerfilters %} @@ -13,4 +13,4 @@ HTTP Error 400 Bad Request.

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/rowers/templates/403.html b/rowers/templates/403.html index 71faf1fd..65394b28 100644 --- a/rowers/templates/403.html +++ b/rowers/templates/403.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "bases.html" %} {% load staticfiles %} {% load rowerfilters %} @@ -13,4 +13,4 @@ Access forbidden

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/rowers/templates/404.html b/rowers/templates/404.html index 5330441a..69d2b396 100644 --- a/rowers/templates/404.html +++ b/rowers/templates/404.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "bases.html" %} {% load staticfiles %} {% load rowerfilters %} @@ -13,4 +13,4 @@ We could not find the page on our server.

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/rowers/templates/500.html b/rowers/templates/500.html index dbb58908..a64a6d92 100644 --- a/rowers/templates/500.html +++ b/rowers/templates/500.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "bases.html" %} {% load staticfiles %} {% load rowerfilters %} @@ -13,4 +13,4 @@ The site reported an internal server error. If this behavior repeats, please inf

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/rowers/templates/bases.html b/rowers/templates/bases.html new file mode 100644 index 00000000..57e283b6 --- /dev/null +++ b/rowers/templates/bases.html @@ -0,0 +1,189 @@ + + + + + + + + + + + + Rowsandall + + + + + {% block meta %} {% endblock %} + + +
+ +
+

 

+
+ {% if user.is_authenticated %} +

Password Change

+ {% else %} +

Forgotten Password?

+ {% endif %} +
+
+ + +
+
+

Free Data and Analysis. For Rowers. By Rowers.

+
+
+ {% if user.rower.rowerplan == 'pro' %} +
Pro Member
+ {% else %} +

 

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

logout

+ + {% else %} +

 

+ {% endif %} + +
+
+ +
+
+ {% if user.is_authenticated %} +

Upload

+ Upload CSV, TCX, FIT data files to rowsandall.com + {% else %} +

Register (free)

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

+ Import +

+ Import workouts from Strava, SportTracks, and C2 logbook + {% else %} +

 

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

+ Workouts +

+ See your list of workouts + {% else %} +

 

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

+ Graphs +

+ See your most recent charts + {% else %} +

 

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

+ Analysis +

+ Analysis of workouts over a period of time + {% else %} +

 

+ {% endif %} +
+
+ {% if user.is_authenticated %} +

+ {{ user.first_name }} +

+ Edit user data, e.g. heart rate zones + + {% else %} +

login

+ {% endif %} +
+
+ + +
+
+ {% block message %} + {% if message %} +

+ {{ message }} +

+ {% endif %} + {% if successmessage %} +

+ {{ successmessage }} +

+ {% endif %} + {% endblock %} +
+
+ {% load tz %} + + {% block content %}{% endblock %} +
+
+ +
+ {% block footer %} + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+ {% endblock %} +
+
+ + + diff --git a/rowers/templates/compatibility.html b/rowers/templates/compatibility.html index 0d47a17b..6dc792cb 100644 --- a/rowers/templates/compatibility.html +++ b/rowers/templates/compatibility.html @@ -16,13 +16,14 @@
  • CrewNerd (TCX)
  • Rowing In Motion (TCX)
  • Speedcoach XL (CSV)
  • -
  • Speedcoach GPS (FIT)
  • +
  • Speedcoach GPS (FIT and CSV)
  • Erg

    @@ -35,7 +36,7 @@

    Export Compatibility

    diff --git a/rowers/templates/frontpage.html b/rowers/templates/frontpage.html index 61e08861..1532f44d 100644 --- a/rowers/templates/frontpage.html +++ b/rowers/templates/frontpage.html @@ -22,8 +22,9 @@ RiM icon RowPro icon ErgStick icon + BoatCoach icon PainSled icon

    -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 94febda1..5d98324d 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -59,10 +59,23 @@ class RowerViewSet(viewsets.ModelViewSet): IsOwnerOrNot, ) + http_method_names = ['get','patch'] + + class FavoriteChartViewSet(viewsets.ModelViewSet): model = FavoriteChart serializer_class = FavoriteChartSerializer - queryset = FavoriteChart.objects.all() + #queryset = FavoriteChart.objects.all() + + def get_queryset(self): + r = Rower.objects.filter(user=self.request.user) + return FavoriteChart.objects.filter(user=r) + + permission_classes = ( + IsOwnerOrNot, + ) + + http_method_names = ['get','put','patch','delete'] class StrokeDataViewSet(viewsets.ModelViewSet): serializer_class = StrokeDataSerializer diff --git a/rowers/views.py b/rowers/views.py index 4b3510e8..34e03ca2 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -266,7 +266,7 @@ def rower_register_view(request): message += "Happy rowing!\n\n\n" message += "Oh, one more thing. The site is currently in beta and is developing fast. Bear with us. Don't hesitate to contact me if anything is broken or doesn't seem to work as advertised." send_mail(subject, message, - 'Sander Roosendaal ', + 'Sander Roosendaal ', [fullemail]) subject2 = "New User" @@ -275,7 +275,7 @@ def rower_register_view(request): message2 += "User name: "+username send_mail(subject2, message2, - 'Rowsandall Server ', + 'Rowsandall Server ', ['roosendaalsander@gmail.com']) return HttpResponseRedirect('/rowers/register/thankyou/') @@ -343,17 +343,6 @@ def add_workout_from_strokedata(user,importid,data,strokedata, rowdatetime = iso8601.parse_date(data['start_date']) except ParseError: rowdatetime = iso8601.parse_date(data['date']) -# try: - # rowdatetime = datetime.datetime.strptime(data['date_utc'],"%Y-%m-%d %H:%M:%S") - # rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) -# except KeyError: -# try: -# rowdatetime = dateutil.parser.parse(data['start_date']) -# rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) -# except: -# rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") -# rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - try: @@ -860,7 +849,7 @@ def workout_tcxemail_view(request,id=0): }) except: successmessage = "" - message = "Something went wrong (strava export) "+str(sys.exc_info()[0]) + message = "Something went wrong (TCX export) "+str(sys.exc_info()[0]) with open("media/c2errors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) timestr = strftime("%Y%m%d-%H%M%S") @@ -925,6 +914,7 @@ def workout_csvemail_view(request,id=0): def workout_strava_upload_view(request,id=0): message = "" r = Rower.objects.get(user=request.user) + res = -1 if (r.stravatoken == '') or (r.stravatoken is None): s = "Token doesn't exist. Need to authorize" return HttpResponseRedirect("/rowers/me/stravaauthorize/") @@ -932,28 +922,29 @@ def workout_strava_upload_view(request,id=0): # ready to upload. Hurray w = Workout.objects.get(id=id) if (checkworkoutuser(request.user,w)): - tcxfile = stravastuff.createstravaworkoutdata(w) + try: + tcxfile = stravastuff.createstravaworkoutdata(w) - - try: with open(tcxfile,'rb') as f: try: res = stravastuff.handle_stravaexport(f,w.name, r.stravatoken, description=w.notes) - except: + w.uploadedtostrava = res + w.save() + os.remove(tcxfile) + url = "/rowers/workout/"+str(w.id)+"/edit" + successmessage = 'Workout sent to Strava.' + except: with open("media/stravaerrors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) - timestr = time.strftime("%Y%m%d-%H%M%S") + timestr = strftime("%Y%m%d-%H%M%S") errorlog.write(timestr+errorstring+"\r\n") errorlog.write("views.py line 946\r\n") + message = 'Error: '+errorstring + - w.uploadedtostrava = res - w.save() - os.remove(tcxfile) - url = "/rowers/workout/"+str(w.id)+"/edit" - successmessage = 'Workout sent to Strava.' url = reverse(workout_export_view, kwargs = { 'id':str(w.id), @@ -968,7 +959,6 @@ def workout_strava_upload_view(request,id=0): url = reverse(workout_export_view, kwargs = { 'id':str(w.id), - 'message':message, }) response = HttpResponseRedirect(url) # except TimeoutExceeded as e: @@ -1009,7 +999,7 @@ def workout_c2_upload_view(request,id=0): message = "Unexpected Error: "+str(sys.exc_info()[0]) with open("media/c2errors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) - timestr = time.strftime("%Y%m%d-%H%M%S") + timestr = strftime("%Y%m%d-%H%M%S") errorlog.write(timestr+errorstring+"\r\n") # check for duplicate error first @@ -1029,7 +1019,7 @@ def workout_c2_upload_view(request,id=0): message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text with open("media/c2errors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) - timestr = time.strftime("%Y%m%d-%H%M%S") + timestr = strftime("%Y%m%d-%H%M%S") errorlog.write(timestr+errorstring+"\r\n") @@ -1038,7 +1028,7 @@ def workout_c2_upload_view(request,id=0): message = "Something went wrong in workout_c2_upload_view. C2 sync failed." with open("media/c2errors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) - timestr = time.strftime("%Y%m%d-%H%M%S") + timestr = strftime("%Y%m%d-%H%M%S") errorlog.write(timestr+errorstring+"\r\n") else: @@ -1073,7 +1063,6 @@ def workout_sporttracks_upload_view(request,id=0): url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first if (response.status_code == 409 ): message = "Duplicate error" @@ -1088,7 +1077,7 @@ def workout_sporttracks_upload_view(request,id=0): return HttpResponseRedirect(url) else: s = response - message = "Something went wrong in workout_sporttracks_upload_view %s" % s + message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason else: message = "You are not authorized to upload this workout" @@ -2338,6 +2327,9 @@ def workout_wind_view(request,id=0,message="",successmessage=""): except KeyError: hascoordinates = 0 + if not latitude.std(): + hascoordinates = 0 + try: bearing = rowdata.df.ix[:,'bearing'].values except KeyError: @@ -3150,10 +3142,14 @@ def workout_edit_view(request,id=0,message="",successmessage=""): if rowdata != 0: try: latitude = rowdata.df[' latitude'] + if not latitude.std(): + hascoordinates = 0 except KeyError,AttributeError: hascoordinates = 0 + else: hascoordinates = 0 + if hascoordinates: res = googlemap_chart(rowdata.df[' latitude'], @@ -3692,6 +3688,7 @@ def workout_getc2workout_view(request,c2id): res = c2stuff.get_c2_workout(request.user,c2id) if (res.status_code == 200): data = res.json()['data'] +<<<<<<< HEAD splitdata = None if 'splits' in data: splitdata = data['splits'] @@ -3719,16 +3716,41 @@ def workout_getc2workout_view(request,c2id): 'message':message, }) return HttpResponseRedirect(url) +======= + if data['stroke_data']: + res2 = c2stuff.get_c2_workout_strokes(request.user,c2id) + else: + message = "This workout does not have any stroke data associated with it" + url = reverse(workout_c2import_view, + kwargs={ + 'message':message, + }) + return HttpResponseRedirect(url) + + if res2.status_code == 200: + strokedata = pd.DataFrame.from_dict(res2.json()['data']) + id = add_workout_from_strokedata(request.user,c2id,data,strokedata, + source='c2') + w = Workout.objects.get(id=id) + w.uploadedtoc2=c2id + w.save() + url = "/rowers/workout/"+str(id)+"/edit" + return HttpResponseRedirect(url) +>>>>>>> develop else: - message = "This workout doesn't contain stroke data" - if settings.DEBUG: - return HttpResponse(res) - else: - url = reverse(workout_c2import_view, - kwargs={ - 'message':message, - }) - return HttpResponseRedirect(url) + # message = json.loads(s.text)['message'] + message = json.loads(res2.text)['message'] + url = reverse(workout_c2import_view, + kwargs={ + 'message':message, + }) + return HttpResponseRedirect(url) + + url = reverse(workout_c2import_view, + kwargs={ + 'message':message, + }) + return HttpResponseRedirect(url) else: message = "Received error code from Concept2" diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 58078fa3..e0b6c354 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -97,6 +97,7 @@ TEMPLATES = [ 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', + 'django.core.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.i18n', @@ -249,7 +250,8 @@ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'mail.rosti.cz' EMAIL_PORT = '25' EMAIL_HOST_USER = 'info@rowsandall.com' -EMAIL_HOST_PASSWORD = 'lnD3mbZ1NoI8RK1StOdO' +#EMAIL_HOST_PASSWORD = 'lnD3mbZ1NoI8RK1StOdO' +EMAIL_HOST_PASSWORD = '0r0wYgQUReOYK7sEkBby' EMAIL_USE_TLS = True # weather stuff diff --git a/static/img/bcsquare.png b/static/img/bcsquare.png new file mode 100644 index 00000000..163cef9b Binary files /dev/null and b/static/img/bcsquare.png differ