988 lines
37 KiB
Python
988 lines
37 KiB
Python
from rowers.views.statements import *
|
|
from rowers.rower_rules import user_is_not_basic, user_is_coachee
|
|
|
|
@login_required()
|
|
def deactivate_user(request):
|
|
pk = request.user.id
|
|
user = User.objects.get(pk=pk)
|
|
user_form = DeactivateUserForm(instance=user)
|
|
if request.user.is_authenticated and request.user.id == user.id:
|
|
if request.method == "POST":
|
|
user_form = DeactivateUserForm(request.POST, instance=user)
|
|
if user_form.is_valid():
|
|
if not user_form.cleaned_data['is_active']:
|
|
r = Rower.objects.get(user=user)
|
|
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
|
|
try:
|
|
subscriptions = braintreestuff.find_subscriptions(
|
|
r)
|
|
for subscription in subscriptions:
|
|
success, themessages, errormessages = braintreestuff.cancel_subscription(
|
|
r, id)
|
|
for message in themessages:
|
|
messages.info(request, message)
|
|
except ProcessorCustomerError:
|
|
pass
|
|
|
|
r.paidplan = None
|
|
r.teamplanexpires = timezone.now()
|
|
r.planexpires = timezone.now()
|
|
r.clubsize = 10
|
|
r.rowerplan = 'basic'
|
|
r.save()
|
|
|
|
deactivate_user = user_form.save(commit=False)
|
|
user.is_active = False
|
|
user.save()
|
|
deactivate_user.save()
|
|
# url = reverse(auth_views.logout_then_login)
|
|
url = '/logout/?next=/login'
|
|
return HttpResponseRedirect(url)
|
|
|
|
return render(request, "userprofile_deactivate.html", {
|
|
"user_form": user_form,
|
|
})
|
|
else: # pragma: no cover
|
|
raise PermissionDenied
|
|
|
|
|
|
@login_required()
|
|
def user_gdpr_optin(request):
|
|
r = getrower(request.user)
|
|
r.gdproptin = False
|
|
r.gdproptindate = None
|
|
r.save()
|
|
nexturl = request.GET.get('next', '/rowers/list-workouts/')
|
|
if r.gdproptin: # pragma: no cover
|
|
return HttpResponseRedirect(nexturl)
|
|
|
|
return render(request, 'gdpr_optin.html', {
|
|
"next": nexturl
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def user_gdpr_confirm(request):
|
|
r = getrower(request.user)
|
|
r.gdproptin = True
|
|
r.gdproptindate = timezone.now()
|
|
r.save()
|
|
|
|
nexturl = request.GET.get('next', '/rowers/list-workouts/')
|
|
|
|
return HttpResponseRedirect(nexturl)
|
|
|
|
|
|
@login_required()
|
|
def remove_user(request):
|
|
pk = request.user.id
|
|
user = User.objects.get(pk=pk)
|
|
user_form = DeleteUserForm(instance=user)
|
|
if request.user.is_authenticated and request.user.id == user.id:
|
|
if request.method == "POST":
|
|
user_form = DeleteUserForm(request.POST, instance=user)
|
|
if user_form.is_valid():
|
|
cd = user_form.cleaned_data
|
|
name = user.first_name+' '+user.last_name
|
|
email = user.email
|
|
|
|
r = Rower.objects.get(user=user)
|
|
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
|
|
try:
|
|
subscriptions = braintreestuff.find_subscriptions(r)
|
|
for subscription in subscriptions:
|
|
success, themessages, errormessages = braintreestuff.cancel_subscription(
|
|
r, id)
|
|
for message in themessages:
|
|
messages.info(request, message)
|
|
except:
|
|
pass
|
|
|
|
if cd['delete_user']:
|
|
# delete workouts
|
|
Workout.objects.filter(user=user.rower).delete()
|
|
# delete planned sessions
|
|
PlannedSession.objects.filter(manager=user).delete()
|
|
|
|
user.delete()
|
|
_ = myqueue(queuehigh,
|
|
handle_sendemail_userdeleted,
|
|
name, email)
|
|
|
|
url = '/logout/?next=/login'
|
|
# url = reverse(auth_views.logout_then_login)
|
|
return HttpResponseRedirect(url)
|
|
return render(request, "userprofile_delete.html", {
|
|
"user_form": user_form,
|
|
})
|
|
else: # pragma: no cover
|
|
raise PermissionDenied
|
|
|
|
|
|
@login_required()
|
|
def survey(request): # pragma: no cover
|
|
|
|
r = getrower(request.user)
|
|
|
|
surveyform = SurveyForm()
|
|
|
|
if request.method == 'POST':
|
|
r.surveydone = True
|
|
r.surveydonedate = timezone.now()
|
|
r.save()
|
|
|
|
nexturl = request.GET.get('next')
|
|
return HttpResponseRedirect(nexturl)
|
|
|
|
context = {
|
|
'teams': get_my_teams(request.user),
|
|
'rower': r,
|
|
'form': surveyform,
|
|
}
|
|
|
|
return render(request, 'survey.html', context)
|
|
|
|
|
|
@login_required()
|
|
def start_trial_view(request):
|
|
r = getrower(request.user)
|
|
|
|
if not can_start_trial(request.user): # pragma: no cover
|
|
messages.error(request, 'You do not qualify for a trial')
|
|
url = '/rowers/paidplans'
|
|
return HttpResponseRedirect(url)
|
|
|
|
r.protrialexpires = timezone.now()+datetime.timedelta(13)
|
|
r.save()
|
|
|
|
url = reverse('workouts_view')
|
|
|
|
messages.info(request, 'We have started your 14 day trial period')
|
|
|
|
subject2 = "User started Pro Trial"
|
|
message2 = "User Started Pro Trial.\n"
|
|
message2 += request.user.email + "\n"
|
|
message2 += "User name: "+request.user.username
|
|
|
|
send_mail(subject2, message2,
|
|
'Rowsandall Server <info@rowsandall.com>',
|
|
['roosendaalsander@gmail.com'])
|
|
|
|
send_template_email('Rowsandall <info@rowsandall.com>',
|
|
[r.user.email],
|
|
'Welcome to the Rowsandall Pro Trial',
|
|
'protrialewelcome.html',
|
|
{'first_name': r.user.first_name,
|
|
'last_name': r.user.last_name})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
|
|
@login_required()
|
|
def user_messages_delete_all(request, userid=0):
|
|
r = getrower(request.user)
|
|
|
|
usermessages = UserMessage.objects.filter(receiver=r)
|
|
for m in usermessages:
|
|
m.delete()
|
|
|
|
messages.info(request,"Messages Deleted")
|
|
|
|
url = reverse('user_messages')
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def user_messages(request,userid=0):
|
|
r = getrequestrowercoachee(request, userid=userid, notpermanent=True)
|
|
usermessages = UserMessage.objects.filter(receiver=r).order_by('-datetime')
|
|
return render(request,'user_messages.html',
|
|
{'usermessages':usermessages,
|
|
'rower':r})
|
|
|
|
@login_required()
|
|
def user_message_delete(request,id=0): # pragma: no cover
|
|
try:
|
|
msg = UserMessage.objects.get(id=id)
|
|
except UserMessage.DoesNotExist:
|
|
messages.error(request,'Could not find this message')
|
|
url = reverse('user_messages')
|
|
return HttpResponseRedirect(url)
|
|
|
|
if msg.receiver == request.user.rower:
|
|
msg.delete()
|
|
messages.info(request,'Deleted message {id}'.format(id=id))
|
|
else:
|
|
messages.error(request,'You are not allowed to delete this message')
|
|
|
|
url = reverse('user_messages')
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
@login_required()
|
|
def user_message_markread(request,id=0): # pragma: no cover
|
|
try:
|
|
msg = UserMessage.objects.get(id=id)
|
|
except UserMessage.DoesNotExist:
|
|
pass
|
|
|
|
if msg.receiver == request.user.rower:
|
|
msg.isread = True
|
|
msg.save()
|
|
messages.info(request,'Marked message {id} read'.format(id=id))
|
|
else:
|
|
messages.error('You are not allowed to change this message')
|
|
|
|
url = reverse('user_messages')
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
|
|
# Page where user can manage his favorite charts
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def rower_favoritecharts_view(request, userid=0):
|
|
message = ''
|
|
r = getrequestrowercoachee(request, userid=userid, notpermanent=True)
|
|
|
|
staticchartform = StaticChartRowerForm(instance=r)
|
|
datasettingsform = DataRowerForm(instance=r)
|
|
|
|
xparam = 'time'
|
|
yparam1 = 'pace'
|
|
yparam2 = 'power'
|
|
yparam3 = 'hr'
|
|
yparam4 = 'spm'
|
|
|
|
xparam = r.chartstacktemplate_x
|
|
yparam1 = r.chartstacktemplate_y[0]
|
|
yparam2 = r.chartstacktemplate_y[1]
|
|
yparam3 = r.chartstacktemplate_y[2]
|
|
yparam4 = r.chartstacktemplate_y[3]
|
|
|
|
initial = {
|
|
'xaxis': xparam,
|
|
'yaxis1': yparam1,
|
|
'yaxis2': yparam2,
|
|
'yaxis3': yparam3,
|
|
'yaxis4': yparam4,
|
|
}
|
|
stackedchartform = StravaChartForm(request, initial=initial)
|
|
|
|
favorites = FavoriteChart.objects.filter(user=r).order_by('id')
|
|
aantal = len(favorites)
|
|
favorites_data = [{'yparam1': f.yparam1,
|
|
'yparam2': f.yparam2,
|
|
'xparam': f.xparam,
|
|
'plottype': f.plottype,
|
|
'workouttype': f.workouttype,
|
|
'reststrokes': f.reststrokes,
|
|
'notes': f.notes, }
|
|
for f in favorites]
|
|
FavoriteChartFormSet = formset_factory(
|
|
FavoriteForm, formset=BaseFavoriteFormSet, extra=0)
|
|
if aantal == 0:
|
|
FavoriteChartFormSet = formset_factory(
|
|
FavoriteForm, formset=BaseFavoriteFormSet, extra=1)
|
|
|
|
workoutnametemplate = r.workoutnametemplate
|
|
WorkoutNameTemplateFormSet = formset_factory(WorkoutNameTemplateElement, extra=1)
|
|
|
|
workoutnametemplate_data = [{'element': element} for element in r.workoutnametemplate]
|
|
workoutnametemplate_formset = WorkoutNameTemplateFormSet(initial=workoutnametemplate_data, prefix='workoutname')
|
|
|
|
if request.method == 'POST' and 'yaxis4' in request.POST:
|
|
stackedchartform = StravaChartForm(request, request.POST)
|
|
if stackedchartform.is_valid():
|
|
r.chartstacktemplate_x = stackedchartform.cleaned_data.get('xaxis')
|
|
r.chartstacktemplate_y = [stackedchartform.cleaned_data.get('yaxis1'),
|
|
stackedchartform.cleaned_data.get('yaxis2'),
|
|
stackedchartform.cleaned_data.get('yaxis3'),
|
|
stackedchartform.cleaned_data.get('yaxis4')]
|
|
r.save()
|
|
messages.info(request, "We have updated your stacked chart settings")
|
|
|
|
if request.method == 'POST' and 'workoutname-TOTAL_FORMS' in request.POST:
|
|
if 'defaults_workoutname' in request.POST:
|
|
r.workoutnametemplate = ['date','name','distance','ownerfirst','ownerlast','duration','boattype','workouttype']
|
|
r.save()
|
|
else:
|
|
workoutnametemplate_formset = WorkoutNameTemplateFormSet(request.POST, prefix='workoutname')
|
|
newworkoutnametemplate = []
|
|
if workoutnametemplate_formset.is_valid():
|
|
for form in workoutnametemplate_formset:
|
|
element = form.cleaned_data.get('element')
|
|
if element != 'None':
|
|
newworkoutnametemplate.append(element)
|
|
|
|
newworkoutnametemplate = [i for i in newworkoutnametemplate if i is not None]
|
|
r.workoutnametemplate = newworkoutnametemplate
|
|
try:
|
|
r.save()
|
|
except IntegrityError:
|
|
messages.error("Something went wrong")
|
|
workoutnametemplate_data = [{'element': element} for element in r.workoutnametemplate]
|
|
workoutnametemplate_formset = WorkoutNameTemplateFormSet(initial=workoutnametemplate_data, prefix='workoutname')
|
|
|
|
|
|
if request.method == 'POST' and 'staticgrids' in request.POST: # pragma: no cover
|
|
staticchartform = StaticChartRowerForm(request.POST, instance=r)
|
|
if staticchartform.is_valid():
|
|
r.staticgrids = staticchartform.cleaned_data.get('staticgrids')
|
|
r.slowpaceerg = staticchartform.cleaned_data.get('slowpaceerg')
|
|
r.fastpaceerg = staticchartform.cleaned_data.get('fastpaceerg')
|
|
r.slowpaceotw = staticchartform.cleaned_data.get('slowpaceotw')
|
|
r.fastpaceotw = staticchartform.cleaned_data.get('fastpaceotw')
|
|
r.staticchartonupload = staticchartform.cleaned_data.get(
|
|
'staticchartonupload')
|
|
r.fav_analysis = staticchartform.cleaned_data.get('fav_analysis')
|
|
r.usersmooth = staticchartform.cleaned_data.get('usersmooth')
|
|
r.save()
|
|
|
|
if request.method == 'POST' and 'save_data' in request.POST: # pragma: no cover
|
|
datasettingsform = DataRowerForm(request.POST, instance=r)
|
|
if datasettingsform.is_valid():
|
|
cd = datasettingsform.cleaned_data
|
|
r.autojoin = cd.get('autojoin')
|
|
r.dosmooth = cd.get('dosmooth')
|
|
r.erg_recalculatepower = cd.get('erg_recalculatepower')
|
|
r.save()
|
|
messages.info(request, "We have updated your data settings")
|
|
|
|
if request.method == 'POST' and 'defaults_data' in request.POST: # pragma: no cover
|
|
defaultsmooth = Rower._meta.get_field('dosmooth').get_default()
|
|
defaultautojoin = Rower._meta.get_field('autojoin').get_default()
|
|
defaultergcalcpower = Rower._meta.get_field(
|
|
'erg_recalculatepower').get_default()
|
|
r.dosmooth = defaultsmooth
|
|
r.autojoin = defaultautojoin
|
|
r.erg_recalculatepower = defaultergcalcpower
|
|
r.save()
|
|
datasettingsform = DataRowerForm(instance=r)
|
|
messages.info(
|
|
request, "We have reset your data settings to the default values")
|
|
|
|
if request.method == 'POST' and 'form-TOTAL_FORMS' in request.POST: # pragma: no cover
|
|
favorites_formset = FavoriteChartFormSet(request.POST)
|
|
if favorites_formset.is_valid():
|
|
new_instances = []
|
|
for favorites_form in favorites_formset:
|
|
yparam1 = favorites_form.cleaned_data.get('yparam1')
|
|
yparam2 = favorites_form.cleaned_data.get('yparam2')
|
|
xparam = favorites_form.cleaned_data.get('xparam')
|
|
plottype = favorites_form.cleaned_data.get('plottype')
|
|
workouttype = favorites_form.cleaned_data.get('workouttype')
|
|
reststrokes = favorites_form.cleaned_data.get('reststrokes')
|
|
notes = favorites_form.cleaned_data.get('notes')
|
|
new_instances.append(FavoriteChart(user=r,
|
|
yparam1=yparam1,
|
|
yparam2=yparam2,
|
|
xparam=xparam,
|
|
plottype=plottype,
|
|
notes=notes,
|
|
workouttype=workouttype,
|
|
reststrokes=reststrokes))
|
|
try:
|
|
with transaction.atomic():
|
|
FavoriteChart.objects.filter(user=r).delete()
|
|
FavoriteChart.objects.bulk_create(new_instances)
|
|
messages.info(request, message)
|
|
if len(new_instances) == 0:
|
|
FavoriteChartFormSet = formset_factory(
|
|
FavoriteForm, formset=BaseFavoriteFormSet, extra=1)
|
|
favorites_formset = FavoriteChartFormSet()
|
|
except IntegrityError:
|
|
message = "something went wrong"
|
|
messages.error(request, message)
|
|
else:
|
|
favorites_formset = FavoriteChartFormSet(initial=favorites_data)
|
|
|
|
context = {
|
|
'favorites_formset': favorites_formset,
|
|
'teams': get_my_teams(request.user),
|
|
'rower': r,
|
|
'stackedchartform': stackedchartform,
|
|
'staticchartform': staticchartform,
|
|
'datasettingsform': datasettingsform,
|
|
'workoutnametemplate_formset': workoutnametemplate_formset,
|
|
}
|
|
|
|
return render(request, 'favoritecharts.html', context)
|
|
|
|
# page where user sets his export settings
|
|
|
|
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def rower_exportsettings_view(request, userid=0):
|
|
attrtokens = {
|
|
'polar_auto_import': 'polartoken',
|
|
'c2_auto_export': 'c2token',
|
|
'c2_auto_import': 'c2token',
|
|
'sporttracks_auto_export': 'sporttrackstoken',
|
|
'strava_auto_export': 'stravatoken',
|
|
'strava_auto_import': 'stravatoken',
|
|
'strava_auto_delete': 'stravatoken',
|
|
'trainingpeaks_auto_export': 'tptoken',
|
|
'rp3_auto_import': 'rp3token',
|
|
'rp3_use_split_power': 'rp3token',
|
|
'nk_auto_import': 'nktoken',
|
|
'intervals_auto_export': 'intervals_token',
|
|
'intervals_resample_to_1s': 'intervals_token',
|
|
}
|
|
r = getrequestrowercoachee(request, userid=userid)
|
|
|
|
forms = {
|
|
'polar': RowerExportFormPolar(instance=r),
|
|
'c2': RowerExportFormConcept2(instance=r),
|
|
'sporttracks': RowerExportFormSportTracks(instance=r),
|
|
'strava': RowerExportFormStrava(instance=r),
|
|
'trainingpeaks': RowerExportFormTrainingPeaks(instance=r),
|
|
'rp3': RowerExportFormRP3(instance=r),
|
|
'intervals': RowerExportFormIntervals(instance=r),
|
|
'nk': RowerExportFormNK(instance=r),
|
|
'garmin': RowerExportFormGarmin(instance=r),
|
|
'imports_are_private': RowerPrivateImportForm(instance=r)
|
|
}
|
|
|
|
if request.method == 'POST':
|
|
form = RowerExportForm(request.POST)
|
|
forms = {
|
|
'polar': RowerExportFormPolar(request.POST, instance=r),
|
|
'c2': RowerExportFormConcept2(request.POST, instance=r),
|
|
'sporttracks': RowerExportFormSportTracks(request.POST, instance=r),
|
|
'strava': RowerExportFormStrava(request.POST, instance=r),
|
|
'trainingpeaks': RowerExportFormTrainingPeaks(request.POST, instance=r),
|
|
'rp3': RowerExportFormRP3(request.POST, instance=r),
|
|
'intervals': RowerExportFormIntervals(request.POST, instance=r),
|
|
'nk': RowerExportFormNK(request.POST, instance=r),
|
|
'garmin': RowerExportFormGarmin(request.POST, instance=r),
|
|
'imports_are_private': RowerPrivateImportForm(request.POST, instance=r),
|
|
}
|
|
if form.is_valid():
|
|
cd = form.cleaned_data
|
|
for attr, value in cd.items():
|
|
doset = True
|
|
try:
|
|
tokenname = attrtokens[attr]
|
|
if (getattr(r, tokenname) == '' or getattr(r, tokenname) is None) and value:
|
|
messages.error(
|
|
request, 'Set '+attr+' but it will not be effective until you create a connection.'
|
|
)
|
|
except KeyError:
|
|
doset = True
|
|
if not user_is_not_basic(r.user): # pragma: no cover
|
|
if not user_is_coachee(r.user):
|
|
doset = False
|
|
if not doset: # pragma: no cover
|
|
before = getattr(r, attr)
|
|
if before == value:
|
|
doset = True
|
|
if doset:
|
|
setattr(r, attr, value)
|
|
else: # pragma: no cover
|
|
if user_is_not_basic(r.user):
|
|
messages.error(
|
|
request, 'Could not set '+attr+'. You need to create the connection first.')
|
|
|
|
|
|
r.save()
|
|
messages.info(request, 'Settings saved')
|
|
else:
|
|
form = RowerExportForm(instance=r)
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': '/rowers/me/edit/',
|
|
'name': 'Profile'
|
|
},
|
|
{
|
|
'url': reverse('rower_exportsettings_view'),
|
|
'name': 'Export Settings'
|
|
}
|
|
]
|
|
|
|
grants = AccessToken.objects.filter(user=request.user)
|
|
try:
|
|
apikey = APIKey.objects.get(user=request.user)
|
|
except APIKey.DoesNotExist:
|
|
apikey = APIKey.objects.create(user=request.user)
|
|
|
|
apps = Application.objects.filter(user=request.user)
|
|
|
|
return render(request, 'rower_exportsettings.html',
|
|
{'form': form,
|
|
'forms': forms,
|
|
'rower': r,
|
|
'breadcrumbs': breadcrumbs,
|
|
'grants': grants,
|
|
'apikey': apikey.key,
|
|
'apps': apps,
|
|
})
|
|
|
|
|
|
# Page where user can set his details
|
|
# Add email address to form so user can change his email address
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def rower_edit_view(request, rowerid=0, userid=0, message=""):
|
|
r = getrequestrowercoachee(
|
|
request, rowerid=rowerid, userid=userid, notpermanent=True)
|
|
|
|
if 'courseshare' in request.GET: # pragma: no cover
|
|
courseshare = request.GET.get('courseshare', "ok")
|
|
if courseshare == 'true':
|
|
r.share_course_results = True
|
|
r.save()
|
|
elif courseshare == 'false':
|
|
r.share_course_results = False
|
|
r.save()
|
|
|
|
rowerid = r.id
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': '/rowers/me/edit/',
|
|
'name': 'Profile'
|
|
},
|
|
{
|
|
'url': reverse('rower_edit_view'),
|
|
'name': 'Account Settings'
|
|
}
|
|
]
|
|
|
|
if request.method == 'POST':
|
|
accountform = AccountRowerForm(request.POST, instance=r)
|
|
userform = UserForm(request.POST, instance=r.user)
|
|
privateform = RowerPrivateImportForm(request.POST, instance=r)
|
|
|
|
if accountform.is_valid() and userform.is_valid() and privateform.is_valid():
|
|
# process
|
|
cd = accountform.cleaned_data
|
|
ucd = userform.cleaned_data
|
|
pcd = privateform.cleaned_data
|
|
|
|
first_name = ucd['first_name']
|
|
last_name = ucd['last_name']
|
|
email = ucd['email']
|
|
sex = cd['sex']
|
|
try:
|
|
offercoaching = cd['offercoaching']
|
|
except KeyError: # pragma: no cover
|
|
offercoaching = False
|
|
autojoin = cd['autojoin']
|
|
adaptiveclass = cd['adaptiveclass']
|
|
defaultlandingpage = cd['defaultlandingpage']
|
|
weightcategory = cd['weightcategory']
|
|
birthdate = cd['birthdate']
|
|
showfavoritechartnotes = cd['showfavoritechartnotes']
|
|
getemailnotifications = cd['getemailnotifications']
|
|
getimportantemails = cd['getimportantemails']
|
|
get_rpe_warnings = cd['get_rpe_warnings']
|
|
share_course_results = cd['share_course_results']
|
|
defaulttimezone = cd['defaulttimezone']
|
|
fav_analysis = cd['fav_analysis']
|
|
usersmooth = cd['usersmooth']
|
|
u = r.user
|
|
if u.email != email and len(email): # pragma: no cover
|
|
resetbounce = True
|
|
else:
|
|
resetbounce = False
|
|
if len(first_name):
|
|
u.first_name = first_name
|
|
u.last_name = last_name
|
|
if len(email): # and check_email_freeforuse(u,email):
|
|
u.email = email
|
|
resetbounce = True
|
|
|
|
emailalternatives = cd['emailalternatives']
|
|
imports_are_private = pcd['imports_are_private']
|
|
|
|
u.save()
|
|
r.defaulttimezone = defaulttimezone
|
|
r.weightcategory = weightcategory
|
|
r.adaptiveclass = adaptiveclass
|
|
r.getemailnotifications = getemailnotifications
|
|
r.getimportantemails = getimportantemails
|
|
r.offercoaching = offercoaching
|
|
r.defaultlandingpage = defaultlandingpage
|
|
r.showfavoritechartnotes = showfavoritechartnotes
|
|
r.share_course_results = share_course_results
|
|
r.imports_are_private = imports_are_private
|
|
r.sex = sex
|
|
r.birthdate = birthdate
|
|
r.autojoin = autojoin
|
|
r.get_rpe_warnings = cd['get_rpe_warnings']
|
|
r.emailalternatives = emailalternatives
|
|
r.fav_analysis = fav_analysis
|
|
r.usersmooth = usersmooth
|
|
|
|
if resetbounce and r.emailbounced: # pragma: no cover
|
|
r.emailbounced = False
|
|
r.save()
|
|
|
|
accountform = AccountRowerForm(instance=r)
|
|
userform = UserForm(instance=u)
|
|
privateform = RowerPrivateImportForm(instance=r)
|
|
successmessage = 'Account Information changed'
|
|
messages.info(request, successmessage)
|
|
else:
|
|
accountform = AccountRowerForm(instance=r)
|
|
userform = UserForm(instance=r.user)
|
|
privateform = RowerPrivateImportForm(instance=r)
|
|
|
|
grants = AccessToken.objects.filter(user=request.user)
|
|
try:
|
|
apikey = APIKey.objects.get(user=request.user)
|
|
except APIKey.DoesNotExist:
|
|
apikey = APIKey.objects.create(user=request.user)
|
|
|
|
|
|
return render(request, 'rower_form.html',
|
|
{
|
|
'teams': get_my_teams(request.user),
|
|
'breadcrumbs': breadcrumbs,
|
|
'grants': grants,
|
|
'userform': userform,
|
|
'accountform': accountform,
|
|
'privateform': privateform,
|
|
'rower': r,
|
|
'apikey': apikey.key,
|
|
})
|
|
|
|
@login_required()
|
|
def rower_regenerate_apikey(request):
|
|
try:
|
|
referer = request.META['HTTP_REFERER']
|
|
except KeyError:
|
|
referer = '/rowers/me/edit/'
|
|
try:
|
|
apikey = APIKey.objects.get(user=request.user)
|
|
except APIKey.DoesNotExist:
|
|
apikey = APIKey.objects.create(user=request.user)
|
|
|
|
apikey.regenerate_key()
|
|
|
|
return HttpResponseRedirect(referer)
|
|
|
|
#simple initial settings page
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def rower_simpleprefs_view(request, userid=0):
|
|
r = getrequestrowercoachee(request, userid=userid, notpermanent=True)
|
|
|
|
firsttime = False
|
|
if not r.ftpset: # pragma: no cover
|
|
r.ftpset = True
|
|
r.save()
|
|
firsttime = True
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': '/rowers/me/edit/',
|
|
'name': 'Profile'
|
|
},
|
|
{
|
|
'url': reverse('rower_simpleprefs_view'),
|
|
'name': 'Zones'
|
|
}
|
|
]
|
|
|
|
form = SimpleRowerPowerForm(instance=r)
|
|
|
|
if request.method == 'POST': # pragma: no cover
|
|
form = SimpleRowerPowerForm(request.POST, instance=r)
|
|
if form.is_valid():
|
|
form.save(commit=True)
|
|
messages.info(request,'FTP and OTW FTP saved')
|
|
if firsttime:
|
|
nexturl = request.GET.get('next', '/rowers/list-workouts/')
|
|
return HttpResponseRedirect(nexturl)
|
|
|
|
|
|
return render(request, 'rower_simplepreferences.html',
|
|
{
|
|
'form': form,
|
|
'teams': get_my_teams(request.user),
|
|
'breadcrumbs': breadcrumbs,
|
|
'rower': r,
|
|
})
|
|
|
|
|
|
|
|
# Page where user can set his details
|
|
# Add email address to form so user can change his email address
|
|
@login_required()
|
|
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
def rower_prefs_view(request, userid=0, message=""):
|
|
r = getrequestrowercoachee(request, userid=userid, notpermanent=True)
|
|
|
|
breadcrumbs = [
|
|
{
|
|
'url': '/rowers/me/edit/',
|
|
'name': 'Profile'
|
|
},
|
|
{
|
|
'url': reverse('rower_prefs_view'),
|
|
'name': 'Zones'
|
|
}
|
|
]
|
|
|
|
form = RowerHRZonesForm(instance=r)
|
|
powerform = RowerPowerForm(instance=r)
|
|
powerzonesform = RowerPowerZonesForm(instance=r)
|
|
cpform = RowerCPForm(instance=r)
|
|
|
|
if request.method == 'POST' and "ut2" in request.POST:
|
|
form = RowerHRZonesForm(request.POST)
|
|
if form.is_valid():
|
|
# something
|
|
cd = form.cleaned_data
|
|
hrmax = cd['max']
|
|
ut2 = cd['ut2']
|
|
ut1 = cd['ut1']
|
|
at = cd['at']
|
|
tr = cd['tr']
|
|
an = cd['an']
|
|
rest = cd['rest']
|
|
|
|
hrrestname = cd['hrrestname']
|
|
hrut2name = cd['hrut2name']
|
|
hrut1name = cd['hrut1name']
|
|
hratname = cd['hratname']
|
|
hrtrname = cd['hrtrname']
|
|
hranname = cd['hranname']
|
|
hrmaxname = cd['hrmaxname']
|
|
hrzones = [hrrestname, hrut2name, hrut1name,
|
|
hratname, hrtrname, hranname, hrmaxname]
|
|
|
|
r.max = max(min(hrmax, 250), 10)
|
|
r.ut2 = max(min(ut2, 250), 10)
|
|
r.ut1 = max(min(ut1, 250), 10)
|
|
r.at = max(min(at, 250), 10)
|
|
r.tr = max(min(tr, 250), 10)
|
|
r.an = max(min(an, 250), 10)
|
|
r.rest = max(min(rest, 250), 10)
|
|
r.hrzones = hrzones
|
|
r.save()
|
|
successmessage = "Your Heart Rate data were changed"
|
|
messages.info(request, successmessage)
|
|
elif request.method == 'POST' and "ftp" in request.POST:
|
|
powerform = RowerPowerForm(request.POST, instance=r)
|
|
if powerform.is_valid():
|
|
powerform.save(commit=True)
|
|
cd = powerform.cleaned_data
|
|
hrftp = cd['hrftp']
|
|
if hrftp == 0: # pragma: no cover
|
|
hrftp = int((r.an+r.tr)/2.)
|
|
cogganzones = cd['cogganzones']
|
|
|
|
powerfrac = 100*np.array([r.pw_ut2,
|
|
r.pw_ut1,
|
|
r.pw_at,
|
|
r.pw_tr, r.pw_an])/r.ftp
|
|
if cogganzones: # pragma: no cover
|
|
powerfrac = np.array([55.,75.,90.,105.,120.])
|
|
powerzones = ['Rest',
|
|
'Active Recovery',
|
|
'Endurance',
|
|
'Tempo',
|
|
'Threshold',
|
|
'Anaerobic']
|
|
r.powerzones = powerzones
|
|
|
|
ut2, ut1, at, tr, an = (r.ftp*powerfrac/100.).astype(int)
|
|
r.pw_ut2 = ut2
|
|
r.pw_ut1 = ut1
|
|
r.pw_at = at
|
|
r.pw_tr = tr
|
|
r.pw_an = an
|
|
r.hrftp = hrftp
|
|
r.save()
|
|
powerzonesform = RowerPowerZonesForm(instance=r)
|
|
|
|
message = "FTP and/or OTW slack values changed."
|
|
messages.info(request, message)
|
|
|
|
elif request.method == 'POST' and "ut3name" in request.POST:
|
|
powerzonesform = RowerPowerZonesForm(request.POST)
|
|
if powerzonesform.is_valid():
|
|
cd = powerzonesform.cleaned_data
|
|
pw_ut2 = cd['pw_ut2']
|
|
pw_ut1 = cd['pw_ut1']
|
|
pw_at = cd['pw_at']
|
|
pw_tr = cd['pw_tr']
|
|
pw_an = cd['pw_an']
|
|
ut3name = cd['ut3name']
|
|
ut2name = cd['ut2name']
|
|
ut1name = cd['ut1name']
|
|
atname = cd['atname']
|
|
trname = cd['trname']
|
|
anname = cd['anname']
|
|
powerzones = [ut3name, ut2name, ut1name, atname, trname, anname]
|
|
|
|
r.pw_ut2 = pw_ut2
|
|
r.pw_ut1 = pw_ut1
|
|
r.pw_at = pw_at
|
|
r.pw_tr = pw_tr
|
|
r.pw_an = pw_an
|
|
r.powerzones = powerzones
|
|
r.save()
|
|
successmessage = "Your Power Zone data were changed"
|
|
messages.info(request, successmessage)
|
|
elif request.method == 'POST' and 'cprange' in request.POST: # pragma: no cover
|
|
cpform = RowerCPForm(request.POST)
|
|
if cpform.is_valid():
|
|
cd = cpform.cleaned_data
|
|
cprange = cd['cprange']
|
|
kfit = cd['kfit']
|
|
kfatigue = cd['kfatigue']
|
|
r.cprange = cprange
|
|
r.kfit = kfit
|
|
r.kfatigue = kfatigue
|
|
r.save()
|
|
messages.info(request, 'Updated CP range and time decay constants')
|
|
_ = dataprep.update_rolling_cp(r, mytypes.otwtypes, 'water')
|
|
_ = dataprep.update_rolling_cp(r, mytypes.otetypes, 'erg')
|
|
|
|
return render(request, 'rower_preferences.html',
|
|
{
|
|
'form': form,
|
|
'teams': get_my_teams(request.user),
|
|
'powerform': powerform,
|
|
'powerzonesform': powerzonesform,
|
|
'breadcrumbs': breadcrumbs,
|
|
'cpform': cpform,
|
|
'rower': r,
|
|
})
|
|
|
|
|
|
# Revoke an app that you granted access through the API.
|
|
# this views is called when you press a button on the User edit page
|
|
# the button is only there when you have granted access to an app
|
|
@login_required()
|
|
def rower_revokeapp_view(request, id=0): # pragma: no cover
|
|
try:
|
|
tokens = AccessToken.objects.filter(user=request.user, application=id)
|
|
refreshtokens = AccessToken.objects.filter(
|
|
user=request.user, application=id)
|
|
for token in tokens:
|
|
token.revoke()
|
|
for token in refreshtokens:
|
|
token.revoke()
|
|
|
|
# r = getrower(request.user)
|
|
# form = RowerForm(instance=r)
|
|
# powerform = RowerPowerForm(instance=r)
|
|
# grants = AccessToken.objects.filter(user=request.user)
|
|
url = reverse('rower_edit_view')
|
|
return HttpResponseRedirect(url)
|
|
except AccessToken.DoesNotExist:
|
|
raise Http404("Access token doesn't exist")
|
|
|
|
|
|
@login_required()
|
|
def rower_update_empower_view(
|
|
request,
|
|
startdate=timezone.now()-datetime.timedelta(days=365),
|
|
enddate=timezone.now()
|
|
): # pragma: no cover
|
|
try:
|
|
r = getrower(request.user)
|
|
except Rower.DoesNotExist:
|
|
raise Http404("Rower doesn't exist")
|
|
|
|
if request.method == 'POST' and 'daterange' in request.POST:
|
|
dateform = DateRangeForm(request.POST)
|
|
if dateform.is_valid():
|
|
startdate = dateform.cleaned_data['startdate']
|
|
enddate = dateform.cleaned_data['enddate']
|
|
startdatestring = startdate.strftime('%Y-%m-%d')
|
|
enddatestring = enddate.strftime('%Y-%m-%d')
|
|
request.session['startdate'] = startdatestring
|
|
request.session['enddate'] = enddatestring
|
|
else:
|
|
dateform = DateRangeForm(initial={
|
|
'startdate': startdate,
|
|
'enddate': enddate,
|
|
})
|
|
|
|
if request.method == 'POST' and 'workouts' in request.POST:
|
|
form = WorkoutMultipleCompareForm(request.POST)
|
|
if form.is_valid():
|
|
cd = form.cleaned_data
|
|
workouts = cd['workouts']
|
|
workoutdicts = []
|
|
|
|
for w in workouts:
|
|
if w.user != r:
|
|
message = "You can only alter your own workouts"
|
|
messages.error(request, message)
|
|
if 'x' in w.boattype and w.oarlength is not None and w.oarlength > 3.30:
|
|
message = "Oarlength and boat type mismatch for workout " + \
|
|
str(w.id)+". Skipping workout"
|
|
messages.error(request, message)
|
|
elif 'x' not in w.boattype and w.oarlength is not None and w.oarlength <= 3.30:
|
|
message = "Oarlength and boat type mismatch for workout " + \
|
|
str(w.id)+". Skipping workout"
|
|
messages.error(request, message)
|
|
elif w.oarlength is None:
|
|
message = "Incorrect oarlength in workout " + \
|
|
str(w.id)+". Skipping workout"
|
|
messages.error(request, message)
|
|
else:
|
|
|
|
workoutdict = {
|
|
'id': w.id,
|
|
'boattype': w.boattype,
|
|
'filename': w.csvfilename,
|
|
'inboard': w.inboard,
|
|
'oarlength': w.oarlength
|
|
}
|
|
|
|
workoutdicts.append(workoutdict)
|
|
|
|
w.workoutsource = 'speedcoach2corrected'
|
|
w.save()
|
|
|
|
job = myqueue(queuelow, handle_update_empower,
|
|
request.user.email, workoutdicts,
|
|
debug=False,
|
|
emailbounced=r.emailbounced)
|
|
|
|
try:
|
|
request.session['async_tasks'] += [(job.id, 'update_empower')]
|
|
except KeyError:
|
|
request.session['async_tasks'] = [(job.id, 'update_empower')]
|
|
|
|
successmessage = 'Your workouts are being updated in the background." \
|
|
" You will receive email when this is done. You can check the status" \
|
|
" of your calculations <a href="/rowers/jobs-status" target="_blank">here</a>'
|
|
|
|
messages.info(request, successmessage)
|
|
|
|
url = reverse('workouts_view')
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
|
|
workouts = Workout.objects.filter(
|
|
startdatetime__gte=startdate,
|
|
startdatetime__lte=enddate,
|
|
workoutsource='speedcoach2',
|
|
user=r,
|
|
).order_by("-date", "-starttime")
|
|
|
|
form = WorkoutMultipleCompareForm()
|
|
form.fields["workouts"].queryset = workouts
|
|
# GET request = prepare form
|
|
|
|
return render(request, 'empower_fix.html',
|
|
{'workouts': workouts,
|
|
'active': 'nav-workouts',
|
|
'dateform': dateform,
|
|
'form': form,
|
|
'rower': r
|
|
})
|