fixes for coach trial
This commit is contained in:
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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+' <a class="remove" href="javascript:void(0);"><b><font color="red">X</font></b></a></div>');
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
|
||||
{% if user.is_authenticated and user|is_manager and rower %}
|
||||
<p> </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> </p>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
{% if user.is_authenticated and user|is_manager and rower %}
|
||||
<p> </p>
|
||||
{% endif %}
|
||||
|
||||
{% if user|coach_rowers %}
|
||||
<ul class="cd-accordion-menu animated">
|
||||
@@ -87,7 +88,6 @@
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if teams %}
|
||||
<p> </p>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user