Private
Public Access
1
0

Merge branch 'feature/teamcom' into develop

This commit is contained in:
Sander Roosendaal
2019-07-31 14:14:21 +02:00
13 changed files with 237 additions and 19 deletions
+7
View File
@@ -1207,6 +1207,13 @@ class WorkoutRaceSelectForm(forms.Form):
# self.fields['evaluate_after'] = # self.fields['evaluate_after'] =
# form to send messages to team members
class TeamMessageForm(forms.Form):
message = forms.CharField(required=True,
initial='',
widget=forms.Textarea()
)
# Form to select team by rower # Form to select team by rower
class RowerTeamForm(forms.Form): class RowerTeamForm(forms.Form):
team = forms.ModelChoiceField( team = forms.ModelChoiceField(
+1 -1
View File
@@ -861,7 +861,7 @@ class Rower(models.Model):
privacy = models.CharField(default='visible',max_length=30, privacy = models.CharField(default='visible',max_length=30,
choices=privacychoices) choices=privacychoices)
team = models.ManyToManyField(Team,blank=True) team = models.ManyToManyField(Team,blank=True,related_name='rower')
# Export and Time Zone Settings # Export and Time Zone Settings
defaulttimezone = models.CharField(default='UTC',max_length=100, defaulttimezone = models.CharField(default='UTC',max_length=100,
+57
View File
@@ -1321,6 +1321,44 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs):
return 1 return 1
@app.task
def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs):
# send email with attachment
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Calendar File for your sessions from Rowsandall.com"
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
siteurl = SITE_URL
if debug:
progressurl = SITE_URL_DEV
siteurl = SITE_URL_DEV
d = {'first_name':first_name,
'siteurl':siteurl,
'url':url,
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'icsemail.html',d,
attach_file=icsfile,**kwargs)
try:
os.remove(csvfile)
except:
pass
return 1
@app.task @app.task
def handle_sendemailfile(first_name, last_name, email, csvfile,**kwargs): def handle_sendemailfile(first_name, last_name, email, csvfile,**kwargs):
@@ -1982,6 +2020,25 @@ def handle_sendemailnewcomment(first_name,
return 1 return 1
@app.task
def handle_sendemail_message(email,fromemail,rowername,message,teamname,managername,
debug=False,**kwargs):
fullemail = email
subject = 'New message from team ' + teamname
from_email = fromemail
d = {
'rowername':rowername,
'teamname':teamname,
'managername':managername,
'message':message,
}
res = send_template_email(from_email,[fullemail],subject,
'teammessage.html',d,**kwargs)
return 1
@app.task @app.task
def handle_sendemail_request(email, name, code, teamname, requestor, id, def handle_sendemail_request(email, name, code, teamname, requestor, id,
+22 -1
View File
@@ -37,6 +37,7 @@ from rowers.tasks import (
handle_sendemail_coachoffer_accepted, handle_sendemail_coachoffer_accepted,
handle_sendemail_coachrequest_rejected, handle_sendemail_coachrequest_rejected,
handle_sendemail_coachrequest_accepted, handle_sendemail_coachrequest_accepted,
handle_sendemail_message,
) )
from rowers.models import ValidationError from rowers.models import ValidationError
@@ -170,11 +171,21 @@ def remove_coach(coach,rower):
return (1,'Coach removed') return (1,'Coach removed')
def rower_get_managers(rower):
managers = []
for team in rower.team.all():
managers.append(team.manager.rower)
return managers
def rower_get_coaches(rower): def rower_get_coaches(rower):
coaches = [] coaches = []
for group in rower.coachinggroups.all(): for group in rower.coachinggroups.all():
try:
coach = Rower.objects.get(mycoachgroup=group) coach = Rower.objects.get(mycoachgroup=group)
coaches.append(coach) coaches.append(coach)
except Rower.DoesNotExist:
pass
return coaches return coaches
@@ -567,7 +578,17 @@ def send_invite_accept_email(invitation):
return (1,'Invitation email sent') return (1,'Invitation email sent')
def send_team_message(team,message):
rowers = team.rower.all()
managername = team.manager.first_name + " " + team.manager.last_name
for rower in rowers:
rowername = rower.user.first_name + " " + rower.user.last_name
res = myqueue(queuehigh,
handle_sendemail_message,
rower.user.email,team.manager.email,rowername,message,team.name,managername)
return (1,'message sent')
def send_request_email(rekwest): def send_request_email(rekwest):
email = rekwest.team.manager.email email = rekwest.team.manager.email
@@ -606,7 +627,7 @@ def process_request_code(manager,code):
rekwest.delete() rekwest.delete()
return result return (result,'The member was added')
def process_invite_code(user,code): def process_invite_code(user,code):
code = code.upper() code = code.upper()
+5 -1
View File
@@ -4,10 +4,14 @@
<p>Dear <strong>{{ first_name }}</strong>,</p> <p>Dear <strong>{{ first_name }}</strong>,</p>
<p> <p>
Please find attached the requested ICS Calendar file. You can import Please find attached the ICS Calendar file for your training sessions. You can import
this file to your calendar app. this file to your calendar app.
</p> </p>
<p>
You can see the training plan here: <a href="{{ siteurl }}{{ url }}">{{ siteurl }}{{ url }}</a>
</p>
<p> <p>
Best Regards, the Rowsandall Team Best Regards, the Rowsandall Team
</p> </p>
+13 -2
View File
@@ -6,9 +6,9 @@
{% block main %} {% block main %}
{% if theteam %} {% if theteam %}
<h1>Coach Overview. Team {{ theteam.name }}</h1> <h1>Group Overview. Team {{ theteam.name }}</h1>
{% else %} {% else %}
<h1>Coach Overview</h1> <h1>Group Overview</h1>
{% endif %} {% endif %}
<ul class="main-content"> <ul class="main-content">
@@ -83,6 +83,17 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<p>
<a href="/rowers/sessions/sendcalendar/user/{{ rower.user.id }}/?when={{ timeperiod }}">
Get Calendar File</a>
</p>
{% if rower|is_coach:rowers %}
<p>
<a href="/rowers/sessions/coach/sendcalendar/user/{{ rower.user.id }}/?when={{ timeperiod }}">
Send Calendar File to all rowers
</a>
</p>
{% endif %}
</li> </li>
{% if unmatchedworkouts %} {% if unmatchedworkouts %}
+13
View File
@@ -72,6 +72,19 @@
</p> </p>
{% endif %} {% endif %}
</li> </li>
<li class="grid_2">
{% if team.manager == user %}
<h2>Message</h2>
<p>Use this form to send a message to all team members by email. </p>
<form enctype="multipart/form-date" action="" method="post">
<table>
{{ groupmessageform.as_table }}
</table>
{% csrf_token %}
<input type="submit" value="Send">
</form>
{% endif %}
</li>
</ul> </ul>
+14
View File
@@ -0,0 +1,14 @@
{% extends "emailbase.html" %}
{% block body %}
<p>Dear <strong>{{ first_name }}</strong>,</p>
<p>
Here is a message from {{ managername }}, the team manager of rowsandall.com team {{ teamname }}.
</p>
<p>
<code>
{{ message }}
</code>
</p>
{% endblock %}
+11
View File
@@ -66,6 +66,17 @@ def strfdelta(tdelta):
return res return res
from rowers.teams import rower_get_managers
@register.filter
def is_coach(rower,rowers):
for r in rowers:
if rower not in rower_get_managers(r):
print(r,rower)
return False
return True
def strfdeltah(tdelta): def strfdeltah(tdelta):
hours, rest = divmod(tdelta.seconds,3600) hours, rest = divmod(tdelta.seconds,3600)
minutes,seconds = divmod(rest,60) minutes,seconds = divmod(rest,60)
+3
View File
@@ -673,6 +673,9 @@ urlpatterns = [
name='plannedsessions_coach_view'), name='plannedsessions_coach_view'),
re_path(r'^sessions/coach/user/(?P<userid>\d+)/$',views.plannedsessions_coach_view, re_path(r'^sessions/coach/user/(?P<userid>\d+)/$',views.plannedsessions_coach_view,
name='plannedsessions_coach_view'), name='plannedsessions_coach_view'),
re_path(r'^sessions/coach/sendcalendar/user/(?P<userid>\d+)/$',
views.plannedsessions_coach_icsemail_view,
name='plannedsessions_coach_icsemail_view'),
re_path(r'^sessions/print/?/$',views.plannedsessions_print_view, re_path(r'^sessions/print/?/$',views.plannedsessions_print_view,
name='plannedsessions_print_view'), name='plannedsessions_print_view'),
re_path(r'^sessions/(?P<id>\d+)/comments/user/(?P<userid>\d+)/$',views.plannedsession_comment_view, re_path(r'^sessions/(?P<id>\d+)/comments/user/(?P<userid>\d+)/$',views.plannedsession_comment_view,
+63
View File
@@ -71,6 +71,69 @@ def plannedsessions_icsemail_view(request,userid=0):
return response return response
@login_required()
def plannedsessions_coach_icsemail_view(request,userid=0):
therower = getrequestplanrower(request,userid=userid)
startdate,enddate = get_dates_timeperiod(request)
if 'coach' in request.user.rower.rowerplan:
sps = get_sessions_manager(request.user,teamid=0,
enddate=enddate,
startdate=startdate)
else:
rteams = therower.team.filter(viewing='allmembers')
sps = get_sessions(therower,startdate=startdate,enddate=enddate)
if therower.rowerplan != 'freecoach':
rowers = [therower]
else:
rowers = []
rowers = list(set(rowers))
cal = Calendar()
cal.add('prodid','rowsandall')
cal.add('version','1.0')
for ps in sps:
event = Event()
comment = '{d} {u} {c}'.format(
d=ps.sessionvalue,
u = ps.sessionunit,
c = ps.criterium)
event.add('summary',ps.name)
event.add('dtstart',ps.preferreddate)
event.add('dtend',ps.preferreddate)
event['uid'] = 'plannedsession_'+str(ps.id)
event.add('description',ps.comment)
event.add('comment',comment)
cal.add_component(event)
icalstring = cal.to_ical()
fname = "media/training_plan_{d1}_{d2}".format(
d1 = startdate.strftime("%Y%m%d"),
d2 = enddate.strftime("%Y%m%d"),
)
url = reverse('plannedsessions_coach_view')+'?when={d1}/{d2}'.format(
d1 = startdate.strftime("%Y-%m-%d"),
d2 = enddate.strftime("%Y-%m-%d"),
)
for rower in rowers:
fname2 = fname+"_{u}.ics".format(u=rower.id)
with open(fname2,'wb') as fop:
fop.write(icalstring)
job = myqueue(queue,handle_sendemail_ical,
rower.user.first_name,
rower.user.last_name,
rower.user.email,
url,
fname2,debug=False)
return HttpResponseRedirect(url)
@login_required() @login_required()
def course_kmldownload_view(request,id=0): def course_kmldownload_view(request,id=0):
+2 -1
View File
@@ -48,7 +48,7 @@ from django.http import (
) )
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from rowers.forms import ( from rowers.forms import (
ForceCurveOptionsForm,HistoForm, ForceCurveOptionsForm,HistoForm,TeamMessageForm,
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm, LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm, TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement, WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,
@@ -183,6 +183,7 @@ from rowers.tasks import (
handle_sendemail_userdeleted, handle_sendemail_userdeleted,
handle_sendemail_raceregistration, handle_sendemail_raceregistration,
handle_sendemail_racesubmission, handle_sendemail_racesubmission,
handle_sendemail_ical,
) )
from scipy.signal import savgol_filter from scipy.signal import savgol_filter
+23 -10
View File
@@ -27,7 +27,7 @@ def team_view(request,id=0,userid=0):
q = q | q2 q = q | q2
if request.method == 'POST' and request.user == t.manager: if request.method == 'POST' and request.user == t.manager and 'email' in request.POST:
inviteform = TeamInviteForm(request.POST) inviteform = TeamInviteForm(request.POST)
inviteform.fields['user'].queryset = q inviteform.fields['user'].queryset = q
@@ -45,12 +45,24 @@ def team_view(request,id=0,userid=0):
else: else:
message = text message = text
messages.error(request,message) messages.error(request,message)
groupmessageform = TeamMessageForm()
elif request.method == 'POST' and request.user == t.manager and 'message' in request.POST:
groupmessageform = TeamMessageForm(request.POST)
inviteform = TeamInviteForm()
if groupmessageform.is_valid():
message = groupmessageform.cleaned_data['message']
teams.send_team_message(t,message)
messages.info(request,'Message was sent to all team members')
groupmessageform = TeamMessageForm()
elif request.user == t.manager: elif request.user == t.manager:
inviteform = TeamInviteForm() inviteform = TeamInviteForm()
inviteform.fields['user'].queryset = q inviteform.fields['user'].queryset = q
groupmessageform = TeamMessageForm()
else: else:
inviteform = '' inviteform = ''
groupmessageform = ''
members = Rower.objects.filter(team=t).order_by('user__last_name','user__first_name') members = Rower.objects.filter(team=t).order_by('user__last_name','user__first_name')
thisteammyrequests = TeamRequest.objects.filter(team=t,user=request.user) thisteammyrequests = TeamRequest.objects.filter(team=t,user=request.user)
@@ -63,7 +75,7 @@ def team_view(request,id=0,userid=0):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_view,kwargs={'id':id}), 'url':reverse(team_view,kwargs={'id':id}),
@@ -78,6 +90,7 @@ def team_view(request,id=0,userid=0):
'teams':get_my_teams(request.user), 'teams':get_my_teams(request.user),
'myteams':myteams, 'myteams':myteams,
'memberteams':memberteams, 'memberteams':memberteams,
'groupmessageform': groupmessageform,
'members':members, 'members':members,
'breadcrumbs':breadcrumbs, 'breadcrumbs':breadcrumbs,
'active':'nav-teams', 'active':'nav-teams',
@@ -98,7 +111,7 @@ def team_leaveconfirm_view(request,id=0):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_view,kwargs={'id':id}), 'url':reverse(team_view,kwargs={'id':id}),
@@ -242,7 +255,7 @@ def rower_teams_view(request,message='',successmessage=''):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
} }
] ]
@@ -328,7 +341,7 @@ def athlete_drop_coach_confirm_view(request,id):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse('rower_teams_view'), 'url':reverse('rower_teams_view'),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse('athlete_drop_coach_confirm_view',kwargs={'id':id}), 'url':reverse('athlete_drop_coach_confirm_view',kwargs={'id':id}),
@@ -355,7 +368,7 @@ def coach_drop_athlete_confirm_view(request,id):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse('rower_teams_view'), 'url':reverse('rower_teams_view'),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse('coach_drop_athlete_confirm_view',kwargs={'id':id}), 'url':reverse('coach_drop_athlete_confirm_view',kwargs={'id':id}),
@@ -609,7 +622,7 @@ def team_edit_view(request,id=0):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_view,kwargs={'id':id}), 'url':reverse(team_view,kwargs={'id':id}),
@@ -675,7 +688,7 @@ def team_create_view(request):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_create_view), 'url':reverse(team_create_view),
@@ -708,7 +721,7 @@ def team_deleteconfirm_view(request,id):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_view,kwargs={'id':id}), 'url':reverse(team_view,kwargs={'id':id}),
@@ -764,7 +777,7 @@ def team_members_stats_view(request,id):
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(rower_teams_view), 'url':reverse(rower_teams_view),
'name': 'Teams' 'name': 'Groups'
}, },
{ {
'url':reverse(team_view,kwargs={'id':id}), 'url':reverse(team_view,kwargs={'id':id}),