Private
Public Access
1
0

fixes for coach trial

This commit is contained in:
Sander Roosendaal
2022-09-04 17:53:16 +02:00
parent 936a524804
commit 86890a8a73
15 changed files with 97 additions and 54 deletions

View File

@@ -531,6 +531,13 @@ class TeamInviteForm(ModelForm):
user = UserFullnameChoiceField(queryset=User.objects.all(), required=False)
email = forms.EmailField(required=False)
def __init__(self, *args, **kwargs):
userid = kwargs.pop('userid',0)
super(TeamInviteForm, self).__init__(*args, **kwargs)
if userid:
self.fields['user'].initial = userid
class Meta:
model = TeamInvite
fields = ['user', 'email']

View File

@@ -138,6 +138,12 @@ def is_staff(user): # pragma: no cover
@rules.predicate
def is_coach(user):
if user is None:
return False
if user.is_anonymous:
return False
if user.rower.coachtrialexpires >= timezone.now().date():
return True
return user.rower.rowerplan in ['coach', 'freecoach']
@@ -157,6 +163,9 @@ def is_planmember(user):
except AttributeError: # pragma: no cover
return False
if user.rower.coachtrialexpires >= timezone.now().date():
return True
return r.rowerplan in ['coach', 'plan'] # freecoach?
@@ -198,7 +207,7 @@ def is_coachtrial(user):
return False # pragma: no cover
ispromember = is_promember | is_protrial
ispromember = is_promember | is_protrial | is_coach | is_coachtrial
can_have_teams = ispromember | is_coach | is_coachtrial
@@ -251,7 +260,7 @@ def is_plantrial(user):
isplanmember = is_planmember | is_plantrial
iscoachmember = is_coach | is_coachtrial
iscoachmember = is_coachtrial | is_coach
@rules.predicate

View File

@@ -314,6 +314,21 @@ def summaryfromsplitdata(splitdata, data, filename, sep='|', workouttype='rower'
return sums, sa, results
@app.task
def handle_remove_workouts_team(ws, t, debug=False, **kwargs):
for w in ws:
w.team.remove(t)
return 1
@app.task
def handle_add_workouts_team(ws, t, debug=False, **kwargs):
for w in ws:
w.team.add(t)
return 1
@app.task
def check_tp_workout_id(workout, location, attempts=5, debug=False, **kwargs):
authorizationstring = str('Bearer ' + workout.user.tptoken)

View File

@@ -42,20 +42,7 @@ queuehigh = django_rq.get_queue('low')
inviteduration = 14 # days
def handle_remove_workouts_team(ws, t):
for w in ws:
w.team.remove(t)
return 1
def handle_add_workouts_team(ws, t):
for w in ws:
w.team.add(t)
return 1
from rowers.tasks import handle_remove_workouts_team, handle_add_workouts_team
def update_team(t, name, manager, private, notes, viewing):
@@ -128,10 +115,17 @@ def add_member(id, rower):
except ValidationError as e: # pragma: no cover
return(0, "Couldn't add member: "+str(e.message))
# if team manager is coach
if is_coach(t.manager):
result = add_coach(t.manager.rower, rower)
# code to add all workouts
ws = Workout.objects.filter(user=rower)
_ = handle_add_workouts_team(ws, t)
_ = myqueue(
queuehigh,
handle_add_workouts_team,
ws, t)
# code to add plannedsessions
plannedsessions = PlannedSession.objects.filter(
@@ -154,7 +148,8 @@ def remove_member(id, rower):
# remove the team from rower's workouts:
ws = Workout.objects.filter(user=rower, team=t)
_ = handle_remove_workouts_team(ws, t)
_ = myqueue(queuehigh,handle_remove_workouts_team,ws, t)
# set_teamplanexpires(rower)
return (id, 'Member removed')

View File

@@ -25,7 +25,7 @@
<div id="id_drop-files" class="drop-files">
<form id="file_form" enctype="multipart/form-data" action="{{ formloc }}" method="post">
<h1>Upload Workout File</h1>
{% if user.is_authenticated and user|is_manager %}
{% if user.is_authenticated and user|coach_rowers %}
<p>Looking for <a href="/rowers/workout/upload/team/">Team Manager
Upload?</a></p>
{% endif %}
@@ -50,7 +50,7 @@
<p>
<table>
{{ optionsform.as_table }}
</table>
</p>
<p>
@@ -60,7 +60,7 @@
If you check "make private", this workout will not be visible to your followers and will not show up in your teams' workouts list. With the Landing Page option, you can select to which (workout related) page you will be
taken after a successfull upload.
</p>
<p>
If you don't have a workout file but have written down the splits,
you can create a workout file yourself from <a href="/static/dummy_workout_template.xls">this template</a>
@@ -68,7 +68,7 @@
<p><b>Select Files with the File button or drag them on the marked area</b></p>
</li>
@@ -91,16 +91,16 @@ $( document ).ready(function() {
|| $(this).val() == 'churchboat'
) {
$('#id_boattype').toggle(true);
} else {
} else {
$('#id_boattype').toggle(false);
$('#id_boattype').val('1x');
$('#id_boattype').val('1x');
}
});
$('#id_workouttype').change();
$('#id_workouttype').change();
});
</script>
<script>
var td = new FormData();
var formdatasetok = false;
@@ -117,13 +117,13 @@ $('#id_workouttype').change();
if (!formdatasetok) {
$("#id_dropregion").remove();
}
if (formdatasetok) {
$(document).ready(function() {
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
console.log("CSRF token",csrftoken);
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
@@ -141,11 +141,11 @@ $('#id_workouttype').change();
$(window).on('dragenter', function() {
$("#id_drop-files").css("background-color","#E9E9E4");
$("#id_dropregion").addClass("watermark").removeClass("invisible");})
$(window).on('dragleave', function() {
$("#id_drop-files").css("background-color","#FFFFFF");
$("#id_dropregion").removeClass("watermark").addClass("invisible");})
var frm = $("#file_form");
if( window.FormData === undefined ) {
@@ -154,7 +154,7 @@ $('#id_workouttype').change();
} else {
console.log('we have formdata');
}
var data = new FormData(frm[0]);
$('#id_file').on('change', function(evt) {
@@ -187,11 +187,11 @@ $('#id_workouttype').change();
data.set($('#id_offline').attr('name'),$('#id_offline').prop('checked'));
console.log("Set offline to True");
$('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done.');
$('#extra_message').addClass('message');
$('#extra_message').addClass('message');
}
}
});
});
$('input').each(function( i ) {
$(this).change(function() {
@@ -211,8 +211,8 @@ $('#id_workouttype').change();
$(this).change(function() {
data.set($(this).attr('name'),$(this).val());
console.log($(this).attr('id'),$(this).attr('name'),$(this).val());
});});
});});
$('select').each(function( i ) {
console.log($(this).attr('name'),$(this).val());
$(this).change(function() {
@@ -253,7 +253,7 @@ $('#id_workouttype').change();
console.log(result," reloading");
location.reload();
};
}
}
});
return false;
});
@@ -295,9 +295,9 @@ $('#id_workouttype').change();
data.set($('#id_offline').attr('name'),$('#id_offline').prop('checked'));
console.log("Set offline to True");
$('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done.');
$('#extra_message').addClass('message');
$('#extra_message').addClass('message');
}
data.set("file",f);
data.set("file",f);
// data.append("file",f);
$("#id_file").replaceWith('<div id="id_file">'+files[0].name+'&nbsp; <a class="remove" href="javascript:void(0);"><b><font color="red">X</font></b></a></div>');

View File

@@ -115,6 +115,7 @@
{% if user.is_authenticated and user|is_manager and rower %}
<p>&nbsp;</p>
{% endif %}
{% if user|coach_rowers %}
<ul class="cd-accordion-menu animated">
@@ -137,7 +138,6 @@
</li>
</ul>
{% endif %}
{% endif %}
{% if user|user_teams %}
<p>&nbsp;</p>

View File

@@ -65,6 +65,7 @@
{% if user.is_authenticated and user|is_manager and rower %}
<p>&nbsp;</p>
{% endif %}
{% if user|coach_rowers %}
<ul class="cd-accordion-menu animated">
@@ -87,7 +88,6 @@
</li>
</ul>
{% endif %}
{% endif %}
{% if teams %}
<p>&nbsp;</p>

View File

@@ -49,7 +49,6 @@ from six import string_types
register = template.Library()
@register.filter
def workoutdate(id): # pragma: no cover
try:
@@ -711,7 +710,8 @@ def team_members(user):
try:
therower = Rower.objects.get(user=user)
if therower.rowerplan == 'basic': # pragma: no cover
return []
if therower.coachtrialexpires < timezone.now().date():
return []
teams = Team.objects.filter(manager=user)
members = Rower.objects.filter(
team__in=teams).distinct().order_by(
@@ -757,13 +757,20 @@ def team_rowers(user): # pragma: no cover
return []
@register.filter
def length(l):
return len(l)
@register.filter
def coach_rowers(user):
if user.is_anonymous:
return []
if user.rower.rowerplan != 'freecoach':
thelist = [user.rower]+[c for c in coach_getcoachees(user.rower)]
else: # pragma: no cover
thelist = [c for c in coach_getcoachees(user.rower)]
return thelist

View File

@@ -69,6 +69,7 @@ class OwnApi(TestCase):
# response must be json
strokedata = json.loads(response.content)
df = pd.DataFrame(strokedata)
self.assertFalse(df.empty)
form_data = {

View File

@@ -261,8 +261,12 @@ urlpatterns = [
name='rower_update_empower_view'),
re_path(r'^agegroupcp/(?P<age>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/user/(?P<userid>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/user/(?P<userid>\d+)/$',
views.agegroupcpview, name='agegroupcpview'),
re_path(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)/$',
views.ajax_agegrouprecords, name='ajax_agegrouprecords'),
re_path(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m/$',
@@ -429,6 +433,8 @@ urlpatterns = [
name='workout_toggle_ranking'),
re_path(r'^workout/upload/team/$', views.team_workout_upload_view,
name='team_workout_upload_view'),
re_path(r'^workout/upload/team/user/(?P<userid>\d+)/$', views.team_workout_upload_view,
name='team_workout_upload_view'),
re_path(r'^workout/upload/(?P<raceid>\d+)/$',
views.workout_upload_view, name='workout_upload_view'),
re_path(r'^workout/upload/$', views.workout_upload_view,

View File

@@ -1763,7 +1763,7 @@ def otwcp_toadmin_view(request, theuser=0,
return response
def agegroupcpview(request, age, normalize=0):
def agegroupcpview(request, age, normalize=0, userid=0):
script, div = interactive_agegroupcpchart(age, normalized=normalize)
response = render(request, 'agegroupcp.html',

View File

@@ -763,7 +763,7 @@ def workout_nkimport_view(request, userid=0, after=0, before=0):
messages.info(
request,
'Your NK logbook workouts will be imported in the background.'
' It may take a few minutes before it appears.')
' It may take a few minutes before they appear.')
url = reverse('workouts_view')
return HttpResponseRedirect(url)
except KeyError:
@@ -1270,7 +1270,7 @@ def workout_stravaimport_view(request, message="", userid=0):
# done, redirect to workouts list
messages.info(request,
'Your Strava workouts will be imported in the background.'
' It may take a few minutes before it appears.')
' It may take a few minutes before they appear.')
url = reverse('workouts_view')
return HttpResponseRedirect(url)
except KeyError: # pragma: no cover
@@ -1815,7 +1815,7 @@ def workout_c2import_view(request, page=1, userid=0, message=""):
messages.info(
request,
'Your Concept2 workouts will be imported in the background.'
' It may take a few minutes before it appears.')
' It may take a few minutes before they appear.')
url = reverse('workouts_view')
return HttpResponseRedirect(url)
except KeyError: # pragma: no cover

View File

@@ -811,7 +811,7 @@ def useractivate(request, uidb64, token): # pragma: no cover
['roosendaalsander@gmail.com'])
messages.info(
request, 'Thank you for your email confirmation. YOu are now signed in to your account.')
request, 'Thank you for your email confirmation. You are now signed in to your account.')
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])
url = reverse('workouts_view')
# if user.rower.rowerplan == 'freecoach':

View File

@@ -1235,11 +1235,14 @@ def iscoachmember(user):
r = Rower(user=user)
r.save()
result = user.is_authenticated and ('coach' in r.rowerplan)
else: # pragma: no cover
result = False
if user.is_authenticated:
if 'coach' in r.rowerplan:
return True
elif r.coachtrialexpires >= timezone.now().date():
return True
return result
return False
# More User/Rower utils

View File

@@ -5398,7 +5398,7 @@ def workout_upload_view(request,
# This is the main view for processing uploaded files
@user_passes_test(iscoachmember, login_url="/rowers/paidplans", redirect_field_name=None,
message="This functionality requires a Coach plan or higher")
def team_workout_upload_view(request, message="",
def team_workout_upload_view(request, userid=0, message="",
successmessage="",
uploadoptions={
'make_plot': False,
@@ -5572,7 +5572,7 @@ def team_workout_upload_view(request, message="",
else:
form = DocumentsForm()
optionsform = TeamUploadOptionsForm(initial=uploadoptions)
rowerform = TeamInviteForm()
rowerform = TeamInviteForm(userid=userid)
rowerform.fields.pop('email')
rowers = Rower.objects.filter(