Merge branch 'release/v12.72'
This commit is contained in:
@@ -2047,6 +2047,147 @@ def leaflet_chart(lat,lon,name=""):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return script,div
|
||||||
|
|
||||||
|
def leaflet_chart_compare(workoutids,labeldict={},startenddict={}):
|
||||||
|
data = []
|
||||||
|
for id in workoutids:
|
||||||
|
w = Workout.objects.get(id=id)
|
||||||
|
rowdata = rdata(w.csvfilename)
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'id':id,
|
||||||
|
'lat':rowdata.df[' latitude'],
|
||||||
|
'lon':rowdata.df[' longitude']
|
||||||
|
})
|
||||||
|
data.append(f)
|
||||||
|
|
||||||
|
df = pd.concat(data,axis=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Throw out 0,0
|
||||||
|
df = df.replace(0,np.nan)
|
||||||
|
df = df.loc[(df!=0).any(axis=1)]
|
||||||
|
df.fillna(method='bfill',axis=0,inplace=True)
|
||||||
|
df.fillna(method='ffill',axis=0,inplace=True)
|
||||||
|
lat = df['lat']
|
||||||
|
lon = df['lon']
|
||||||
|
if lat.empty or lon.empty:
|
||||||
|
return [0,"invalid coordinate data"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
coordinates = zip(lat,lon)
|
||||||
|
|
||||||
|
scoordinates = "["
|
||||||
|
|
||||||
|
for x,y in coordinates:
|
||||||
|
scoordinates += """[{x},{y}],
|
||||||
|
""".format(
|
||||||
|
x=x,
|
||||||
|
y=y
|
||||||
|
)
|
||||||
|
|
||||||
|
scoordinates += "]"
|
||||||
|
|
||||||
|
script = """
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var streets = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/streets-v11',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
satellite = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/satellite-v9',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
),
|
||||||
|
|
||||||
|
outdoors = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/outdoors-v11',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var mymap = L.map('map_canvas', {{
|
||||||
|
center: [{latmean}, {lonmean}],
|
||||||
|
zoom: 13,
|
||||||
|
layers: [streets, satellite]
|
||||||
|
}}).setView([{latmean},{lonmean}], 13);
|
||||||
|
|
||||||
|
var navionics = new JNC.Leaflet.NavionicsOverlay({{
|
||||||
|
navKey: 'Navionics_webapi_03205',
|
||||||
|
chartType: JNC.NAVIONICS_CHARTS.NAUTICAL,
|
||||||
|
isTransparent: true,
|
||||||
|
zIndex: 1
|
||||||
|
}});
|
||||||
|
|
||||||
|
|
||||||
|
var osmUrl2='http://tiles.openseamap.org/seamark/{{z}}/{{x}}/{{y}}.png';
|
||||||
|
var osmUrl='http://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png';
|
||||||
|
|
||||||
|
|
||||||
|
//create two TileLayer
|
||||||
|
var nautical=new L.TileLayer(osmUrl,{{
|
||||||
|
maxZoom:18}});
|
||||||
|
|
||||||
|
|
||||||
|
L.control.layers({{
|
||||||
|
"Streets": streets,
|
||||||
|
"Satellite": satellite,
|
||||||
|
"Outdoors": outdoors,
|
||||||
|
"Nautical": nautical,
|
||||||
|
}},{{
|
||||||
|
"Navionics":navionics,
|
||||||
|
}}).addTo(mymap);
|
||||||
|
|
||||||
|
var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap);
|
||||||
|
marker.bindPopup("<b>Start</b>");
|
||||||
|
var emarker = new L.marker([{latend}, {longend}]).addTo(mymap);
|
||||||
|
emarker.bindPopup("<b>End</b>");
|
||||||
|
|
||||||
|
var latlongs = {scoordinates}
|
||||||
|
var polyline = L.polyline(latlongs, {{color:'red'}}).addTo(mymap)
|
||||||
|
mymap.fitBounds(polyline.getBounds())
|
||||||
|
|
||||||
|
</script>
|
||||||
|
""".format(
|
||||||
|
latmean=latmean,
|
||||||
|
lonmean=lonmean,
|
||||||
|
latbegin = latbegin,
|
||||||
|
latend=latend,
|
||||||
|
longbegin=longbegin,
|
||||||
|
longend=longend,
|
||||||
|
scoordinates=scoordinates,
|
||||||
|
)
|
||||||
|
|
||||||
|
div = """
|
||||||
|
<div id="map_canvas" style="width: 100%; height: 100%; min-height: 100vh"><p> </p></div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return script,div
|
return script,div
|
||||||
|
|
||||||
def leaflet_chart2(lat,lon,name=""):
|
def leaflet_chart2(lat,lon,name=""):
|
||||||
@@ -5057,7 +5198,7 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
|
|||||||
'time','pace','workoutstate',
|
'time','pace','workoutstate',
|
||||||
'workoutid']
|
'workoutid']
|
||||||
|
|
||||||
datadf = dataprep.getsmallrowdata_db(columns,ids=ids)
|
datadf = dataprep.getsmallrowdata_db(columns,ids=ids,doclean=False,compute=False)
|
||||||
datadf.dropna(axis=1,how='all',inplace=True)
|
datadf.dropna(axis=1,how='all',inplace=True)
|
||||||
datadf.dropna(axis=0,how='any',inplace=True)
|
datadf.dropna(axis=0,how='any',inplace=True)
|
||||||
|
|
||||||
|
|||||||
@@ -2917,6 +2917,17 @@ def update_duplicates_on_delete(sender, instance, **kwargs):
|
|||||||
# conn.close()
|
# conn.close()
|
||||||
# engine.dispose()
|
# engine.dispose()
|
||||||
|
|
||||||
|
class VirtualRaceFollower(models.Model):
|
||||||
|
user = models.ForeignKey(User,on_delete=models.CASCADE,null=True)
|
||||||
|
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
||||||
|
emailaddress = models.EmailField(max_length=254,blank=True,null=True,
|
||||||
|
verbose_name="Email Address")
|
||||||
|
|
||||||
|
class FollowerForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = VirtualRaceFollower
|
||||||
|
fields = ['emailaddress']
|
||||||
|
|
||||||
# Virtual Race results (for keeping results when workouts are deleted)
|
# Virtual Race results (for keeping results when workouts are deleted)
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class VirtualRaceResult(models.Model):
|
class VirtualRaceResult(models.Model):
|
||||||
|
|||||||
39
rowers/templates/followerform.html
Normal file
39
rowers/templates/followerform.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% load tz %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Follow Virtual Challenge{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<h1>Follow {{ plannedession.name }}</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_2">
|
||||||
|
<p>To follow this challenge and receive all news per email, fill out your
|
||||||
|
email address and submit the form.
|
||||||
|
</li>
|
||||||
|
<li class="grid_2">
|
||||||
|
<form enctype="multipart/form-data" method="post">
|
||||||
|
<table width=100%>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" value="Save">
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% if 'racing' in active %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% else %}
|
||||||
|
{% include 'menu_plan.html' %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
49
rowers/templates/mapcompare.html
Normal file
49
rowers/templates/mapcompare.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}View Comparison {% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<script src="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
|
<script async="true" type="text/javascript">
|
||||||
|
Bokeh.set_log_level("info");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
|
<h1>Interactive Comparison</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_4">
|
||||||
|
<div>
|
||||||
|
{{ the_div|safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="grid_4">
|
||||||
|
<form enctype="multipart/form-data" action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{{ chartform.as_table }}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<input name='workoutselectform' class="button green" type="submit" value="Submit">
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% if active == 'nav-racing' %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% else %}
|
||||||
|
{% include 'menu_workouts.html' %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
@@ -65,7 +65,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if button == 'resubmitbutton' %}
|
{% if button == 'resubmitbutton' %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/submit/">Submit New Result</a>
|
<a href="/rowers/virtualevent/{{ race.id }}/submit/">
|
||||||
|
<i class="fas fa-file-plus fa-fw"></i> Submit New Result
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if button == 'withdrawbutton' %}
|
{% if button == 'withdrawbutton' %}
|
||||||
|
|||||||
@@ -160,12 +160,16 @@
|
|||||||
<div id="registerbuttons">
|
<div id="registerbuttons">
|
||||||
{% if request.user.is_anonymous %}
|
{% if request.user.is_anonymous %}
|
||||||
<p>
|
<p>
|
||||||
Registered users of rowsandall.com can participate in this challenge. Participation is free, unless specified differently in the race comment above.
|
Registered users of rowsandall.com can participate in this challenge.
|
||||||
|
Participation is free, unless specified differently in the race comment above.
|
||||||
{% if race.sessiontype == 'race' %}
|
{% if race.sessiontype == 'race' %}
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
|
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if request.user|isfollower:race.id %}
|
||||||
|
<a href="/rowers/virtualevent/{{ race.id }}/follow/"><h3>Follow this challenge</h3></a>
|
||||||
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>
|
<p>
|
||||||
@@ -184,6 +188,9 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if request.user|isfollower:race.id %}
|
||||||
|
<a href="/rowers/virtualevent/{{ race.id }}/follow/"><h3>Follow this challenge</h3></a>
|
||||||
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if button == 'submitbutton' %}
|
{% if button == 'submitbutton' %}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ from rowers.utils import calculate_age
|
|||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
course_length,WorkoutComment,
|
course_length,WorkoutComment,
|
||||||
TrainingMacroCycle,TrainingMesoCycle, TrainingMicroCycle,
|
TrainingMacroCycle,TrainingMesoCycle, TrainingMicroCycle,
|
||||||
Rower,Workout,SiteAnnouncement, TeamInvite, TeamRequest, CoachOffer,CoachRequest
|
Rower,Workout,SiteAnnouncement, TeamInvite, TeamRequest, CoachOffer,CoachRequest,
|
||||||
|
VirtualRaceFollower,VirtualRace,
|
||||||
)
|
)
|
||||||
from rowers.plannedsessions import (
|
from rowers.plannedsessions import (
|
||||||
race_can_register, race_can_submit,race_rower_status
|
race_can_register, race_can_submit,race_rower_status
|
||||||
@@ -40,6 +41,21 @@ from django.template.defaultfilters import stringfilter
|
|||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def isfollower(user,id):
|
||||||
|
|
||||||
|
if user.is_anonymous:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
race = VirtualRace.objects.get(id=id)
|
||||||
|
except VirtualRace.DoesNotExist:
|
||||||
|
return False
|
||||||
|
|
||||||
|
followers = VirtualRaceFollower.objects.filter(race=race,user=user)
|
||||||
|
|
||||||
|
|
||||||
|
return followers.count()==0
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def adaptive(s):
|
def adaptive(s):
|
||||||
u = s
|
u = s
|
||||||
|
|||||||
@@ -346,6 +346,8 @@ urlpatterns = [
|
|||||||
views.virtualevent_uploadimage_view,name='virtualevent_uploadimage_view'),
|
views.virtualevent_uploadimage_view,name='virtualevent_uploadimage_view'),
|
||||||
re_path(r'^virtualevent/(?P<id>\d+)/setimage/(?P<logoid>\d+)/$',
|
re_path(r'^virtualevent/(?P<id>\d+)/setimage/(?P<logoid>\d+)/$',
|
||||||
views.virtualevent_setlogo_view,name='virtualevent_setlog_view'),
|
views.virtualevent_setlogo_view,name='virtualevent_setlog_view'),
|
||||||
|
re_path(r'^virtualevent/(?P<id>\d+)/follow/$',
|
||||||
|
views.addfollower_view,name='addfollower_view'),
|
||||||
re_path(r'^logo/(?P<id>\d+)/delete/$',
|
re_path(r'^logo/(?P<id>\d+)/delete/$',
|
||||||
views.logo_delete_view,name='logo_delete_view'),
|
views.logo_delete_view,name='logo_delete_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/darkskywind/$',views.workout_downloadwind_view,name='workout_downloadwind_view'),
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/darkskywind/$',views.workout_downloadwind_view,name='workout_downloadwind_view'),
|
||||||
|
|||||||
@@ -1625,6 +1625,39 @@ def virtualevent_addboat_view(request,id=0):
|
|||||||
"You have successfully registered for this race. Good luck!"
|
"You have successfully registered for this race. Good luck!"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
otherrecords = VirtualRaceResult.objects.filter(
|
||||||
|
race = race).exclude(userid = r.id)
|
||||||
|
|
||||||
|
for otherrecord in otherrecords:
|
||||||
|
otheruser = Rower.objects.get(id=otherrecord.userid)
|
||||||
|
othername = otheruser.user.first_name+' '+otheruser.user.last_name
|
||||||
|
registeredname = r.user.first_name+' '+r.user.last_name
|
||||||
|
if otherrecord.emailnotifications:
|
||||||
|
job = myqueue(
|
||||||
|
queue,
|
||||||
|
handle_sendemail_raceregistration,
|
||||||
|
otheruser.user.email, othername,
|
||||||
|
registeredname,
|
||||||
|
race.name,
|
||||||
|
race.id
|
||||||
|
)
|
||||||
|
|
||||||
|
followers = VirtualRaceFollower.objects.filter(race = race)
|
||||||
|
|
||||||
|
for follower in followers:
|
||||||
|
othername = ''
|
||||||
|
if follower.user:
|
||||||
|
othername = follower.user.first_name+' '+follower.user.last_name
|
||||||
|
|
||||||
|
registeredname = r.user.first_name+' '+r.user.last_name
|
||||||
|
email = follower.emailaddress
|
||||||
|
job = myqueue(
|
||||||
|
queue,
|
||||||
|
handle_sendemail_raceregistration,
|
||||||
|
email, othername,
|
||||||
|
registeredname,race.name,race.id,
|
||||||
|
)
|
||||||
|
|
||||||
url = reverse('virtualevent_view',
|
url = reverse('virtualevent_view',
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'id':race.id
|
'id':race.id
|
||||||
@@ -1804,7 +1837,12 @@ def virtualevent_register_view(request,id=0):
|
|||||||
|
|
||||||
add_rower_race(r,race)
|
add_rower_race(r,race)
|
||||||
|
|
||||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
# remove followers
|
||||||
|
myfollows = VirtualRaceFollower.objects.filter(user=r.user,race=race)
|
||||||
|
for f in myfollows:
|
||||||
|
f.delete()
|
||||||
|
|
||||||
|
otherrecords = VirtualRaceResult.objects.filter(
|
||||||
race = race).exclude(userid = r.id)
|
race = race).exclude(userid = r.id)
|
||||||
|
|
||||||
for otherrecord in otherrecords:
|
for otherrecord in otherrecords:
|
||||||
@@ -1821,6 +1859,22 @@ def virtualevent_register_view(request,id=0):
|
|||||||
race.id
|
race.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
followers = VirtualRaceFollower.objects.filter(race = race)
|
||||||
|
|
||||||
|
for follower in followers:
|
||||||
|
othername = ''
|
||||||
|
if follower.user:
|
||||||
|
othername = follower.user.first_name+' '+follower.user.last_name
|
||||||
|
|
||||||
|
registeredname = r.user.first_name+' '+r.user.last_name
|
||||||
|
email = follower.emailaddress
|
||||||
|
job = myqueue(
|
||||||
|
queue,
|
||||||
|
handle_sendemail_raceregistration,
|
||||||
|
email, othername,
|
||||||
|
registeredname,race.name,race.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
@@ -2039,6 +2093,11 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
|
|
||||||
add_rower_race(r,race)
|
add_rower_race(r,race)
|
||||||
|
|
||||||
|
# remove followers
|
||||||
|
myfollows = VirtualRaceFollower.objects.filter(user=r.user,race=race)
|
||||||
|
for f in myfollows:
|
||||||
|
f.delete()
|
||||||
|
|
||||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
||||||
race = race).exclude(userid = r.id)
|
race = race).exclude(userid = r.id)
|
||||||
|
|
||||||
@@ -2056,6 +2115,22 @@ def indoorvirtualevent_register_view(request,id=0):
|
|||||||
race.id
|
race.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
followers = VirtualRaceFollower.objects.filter(race = race)
|
||||||
|
|
||||||
|
for follower in followers:
|
||||||
|
othername = ''
|
||||||
|
if follower.user:
|
||||||
|
othername = follower.user.first_name+' '+follower.user.last_name
|
||||||
|
|
||||||
|
registeredname = r.user.first_name+' '+r.user.last_name
|
||||||
|
email = follower.emailaddress
|
||||||
|
job = myqueue(
|
||||||
|
queue,
|
||||||
|
handle_sendemail_raceregistration,
|
||||||
|
email, othername,
|
||||||
|
registeredname,race.name,race.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
messages.info(
|
messages.info(
|
||||||
request,
|
request,
|
||||||
@@ -2734,6 +2809,7 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0):
|
|||||||
if not jobid:
|
if not jobid:
|
||||||
messages.info(request,"Result submitted successfully.")
|
messages.info(request,"Result submitted successfully.")
|
||||||
|
|
||||||
|
|
||||||
for otherrecord in otherrecords:
|
for otherrecord in otherrecords:
|
||||||
try:
|
try:
|
||||||
otheruser = Rower.objects.get(id=otherrecord.userid)
|
otheruser = Rower.objects.get(id=otherrecord.userid)
|
||||||
@@ -2751,7 +2827,21 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0):
|
|||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
followers = VirtualRaceFollower.objects.filter(race = race)
|
||||||
|
|
||||||
|
for follower in followers:
|
||||||
|
othername = ''
|
||||||
|
if follower.user:
|
||||||
|
othername = follower.user.first_name+' '+follower.user.last_name
|
||||||
|
|
||||||
|
registeredname = r.user.first_name+' '+r.user.last_name
|
||||||
|
email = follower.emailaddress
|
||||||
|
job = myqueue(
|
||||||
|
queue,
|
||||||
|
handle_sendemail_racesubmission,
|
||||||
|
email, othername,
|
||||||
|
registeredname,race.name,race.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# redirect to race page
|
# redirect to race page
|
||||||
@@ -2820,3 +2910,71 @@ def virtualevent_submit_result_view(request,id=0,workoutid=0):
|
|||||||
'rower':r,
|
'rower':r,
|
||||||
'w_form':w_form,
|
'w_form':w_form,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def addfollower_view(request,id=0):
|
||||||
|
try:
|
||||||
|
race = VirtualRace.objects.get(id=id)
|
||||||
|
except VirtualRace.DoesNotExist:
|
||||||
|
raise Http404("Virtual Challenge does not exist")
|
||||||
|
|
||||||
|
if not request.user.is_anonymous:
|
||||||
|
follower = VirtualRaceFollower(
|
||||||
|
user=request.user,
|
||||||
|
race=race,
|
||||||
|
emailaddress = request.user.email
|
||||||
|
)
|
||||||
|
follower.save()
|
||||||
|
messages.info(request,"You will receive challenge notifications per email")
|
||||||
|
url = reverse(virtualevent_view,
|
||||||
|
kwargs={'id':id})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
# Anonymous
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = FollowerForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
email = form.cleaned_data['emailaddress']
|
||||||
|
|
||||||
|
follower = VirtualRaceFollower(
|
||||||
|
race=race,
|
||||||
|
emailaddress = email
|
||||||
|
)
|
||||||
|
follower.save()
|
||||||
|
|
||||||
|
messages.info(request,"You will receive challenge notifications per email")
|
||||||
|
|
||||||
|
url = reverse(virtualevent_view,
|
||||||
|
kwargs={'id':id})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
else:
|
||||||
|
form = FollowerForm()
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
'url':reverse('virtualevents_view'),
|
||||||
|
'name': 'Challenges'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url':reverse('virtualevent_view',
|
||||||
|
kwargs={'id':race.id}
|
||||||
|
),
|
||||||
|
'name': race.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url': reverse(addfollower_view,
|
||||||
|
kwargs = {'id':race.id}
|
||||||
|
),
|
||||||
|
'name': 'Follow'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return render(request,'followerform.html',
|
||||||
|
{
|
||||||
|
'form':form,
|
||||||
|
'active':'nav-racing',
|
||||||
|
'breadcrumbs':breadcrumbs,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ from rowers.models import (
|
|||||||
PlannedSessionComment,CoachRequest,CoachOffer,
|
PlannedSessionComment,CoachRequest,CoachOffer,
|
||||||
VideoAnalysis,ShareKey,
|
VideoAnalysis,ShareKey,
|
||||||
StandardCollection,CourseStandard,
|
StandardCollection,CourseStandard,
|
||||||
|
VirtualRaceFollower,
|
||||||
)
|
)
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
||||||
@@ -129,7 +130,8 @@ from rowers.models import (
|
|||||||
VirtualRaceForm,VirtualRaceResultForm,RowerImportExportForm,
|
VirtualRaceForm,VirtualRaceResultForm,RowerImportExportForm,
|
||||||
IndoorVirtualRaceResultForm,IndoorVirtualRaceResult,
|
IndoorVirtualRaceResultForm,IndoorVirtualRaceResult,
|
||||||
IndoorVirtualRaceForm,PlannedSessionCommentForm,
|
IndoorVirtualRaceForm,PlannedSessionCommentForm,
|
||||||
Alert, Condition, StaticChartRowerForm
|
Alert, Condition, StaticChartRowerForm,
|
||||||
|
FollowerForm,
|
||||||
)
|
)
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement,BasePlannedSessionFormSet,
|
FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement,BasePlannedSessionFormSet,
|
||||||
|
|||||||
Reference in New Issue
Block a user