Merge branch 'release/v22.1.0'
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
from rules.permissions import ObjectPermissionBackend
|
||||||
|
from rowers.models import User
|
||||||
|
|
||||||
|
class MyObjectPermissionBackend(ObjectPermissionBackend):
|
||||||
|
def user_can_authenticate(self, user):
|
||||||
|
return getattr(user, "is_active", True)
|
||||||
|
|
||||||
|
def get_user(self, user_id):
|
||||||
|
try:
|
||||||
|
user = User.objects.get(pk=user_id)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return None
|
||||||
|
return user if self.user_can_authenticate(user) else None
|
||||||
|
|
||||||
@@ -1213,6 +1213,7 @@ class ForceCurveMultipleCompareForm(forms.Form):
|
|||||||
bulkactions = (
|
bulkactions = (
|
||||||
('remove','remove'),
|
('remove','remove'),
|
||||||
('export','export'),
|
('export','export'),
|
||||||
|
('rower assign','rower assign'),
|
||||||
)
|
)
|
||||||
destinations = (
|
destinations = (
|
||||||
('C2','C2'),
|
('C2','C2'),
|
||||||
@@ -1230,6 +1231,15 @@ class ExportChoices(forms.Form):
|
|||||||
choices=destinations, label='Destination', required=False, initial='strava'
|
choices=destinations, label='Destination', required=False, initial='strava'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class AssignChoices(forms.Form):
|
||||||
|
remove_workout = forms.BooleanField(initial=False, required=False)
|
||||||
|
destination = forms.ModelMultipleChoiceField(label='Rowers', required=False,
|
||||||
|
queryset=Rower.objects.filter(), widget=forms.CheckboxSelectMultiple())
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(AssignChoices, self).__init__(*args, **kwargs)
|
||||||
|
self.fields['destination'].queryset = Rower.objects.filter()
|
||||||
|
|
||||||
class WorkoutMultipleCompareForm(forms.Form):
|
class WorkoutMultipleCompareForm(forms.Form):
|
||||||
workouts = forms.ModelMultipleChoiceField(
|
workouts = forms.ModelMultipleChoiceField(
|
||||||
queryset=Workout.objects.filter(),
|
queryset=Workout.objects.filter(),
|
||||||
|
|||||||
@@ -324,6 +324,50 @@ def summaryfromsplitdata(splitdata, data, filename, sep='|', workouttype='rower'
|
|||||||
|
|
||||||
return sums, sa, results
|
return sums, sa, results
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def handle_assignworkouts(workouts, rowers, remove_workout, debug=False, **kwargs):
|
||||||
|
for workout in workouts:
|
||||||
|
uploadoptions = {
|
||||||
|
'secret': UPLOAD_SERVICE_SECRET,
|
||||||
|
'title': workout.name,
|
||||||
|
'boattype': workout.boattype,
|
||||||
|
'workouttype': workout.workouttype,
|
||||||
|
'inboard': workout.inboard,
|
||||||
|
'oarlength': workout.oarlength,
|
||||||
|
'summary': workout.summary,
|
||||||
|
'elapsedTime': 3600.*workout.duration.hour+60*workout.duration.minute+workout.duration.second,
|
||||||
|
'totalDistance': workout.distance,
|
||||||
|
'useImpeller': workout.impeller,
|
||||||
|
'seatNumber': workout.seatnumber,
|
||||||
|
'boatName': workout.boatname,
|
||||||
|
'portStarboard': workout.empowerside,
|
||||||
|
}
|
||||||
|
for rower in rowers:
|
||||||
|
failed = False
|
||||||
|
csvfilename = 'media/{code}.csv'.format(code=uuid4().hex[:16])
|
||||||
|
try:
|
||||||
|
with open(csvfilename,'wb') as f:
|
||||||
|
shutil.copy(workout.csvfilename,csvfilename)
|
||||||
|
except FileNotFoundError:
|
||||||
|
try:
|
||||||
|
with open(csvfilename,'wb') as f:
|
||||||
|
csvfilename = csvfilename+'.gz'
|
||||||
|
shutil.copy(workout.csvfilename+'.gz', csvfilename)
|
||||||
|
except:
|
||||||
|
failed = True
|
||||||
|
if not failed:
|
||||||
|
uploadoptions['user'] = rower.user.id
|
||||||
|
uploadoptions['file'] = csvfilename
|
||||||
|
session = requests.session()
|
||||||
|
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
||||||
|
session.headers.update(newHeaders)
|
||||||
|
response = session.post(UPLOAD_SERVICE_URL, json=uploadoptions)
|
||||||
|
print(response.text)
|
||||||
|
if remove_workout:
|
||||||
|
workout.delete()
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_post_workout_api(uploadoptions, debug=False, **kwargs): # pragma: no cover
|
def handle_post_workout_api(uploadoptions, debug=False, **kwargs): # pragma: no cover
|
||||||
session = requests.session()
|
session = requests.session()
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
{{ exportchoice.as_p }}
|
{{ exportchoice.as_p }}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if action == 'rower assign' %}
|
||||||
|
<p>
|
||||||
|
{{ assignchoices.as_p }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ def team_rowers(user): # pragma: no cover
|
|||||||
teams = Team.objects.filter(manager=user)
|
teams = Team.objects.filter(manager=user)
|
||||||
members = Rower.objects.filter(
|
members = Rower.objects.filter(
|
||||||
team__in=teams).distinct().order_by(
|
team__in=teams).distinct().order_by(
|
||||||
"user__last_name", "user__last_name").exclude(
|
"user__last_name", "user__first_name").exclude(
|
||||||
rowerplan='freecoach')
|
rowerplan='freecoach')
|
||||||
return members
|
return members
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -2,7 +2,7 @@ from django.utils.encoding import force_bytes, force_str
|
|||||||
from rowers.tokens import account_activation_token
|
from rowers.tokens import account_activation_token
|
||||||
from django.contrib.sites.shortcuts import get_current_site
|
from django.contrib.sites.shortcuts import get_current_site
|
||||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||||||
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
|
||||||
@@ -817,7 +817,7 @@ def useractivate(request, uidb64, token): # pragma: no cover
|
|||||||
|
|
||||||
messages.info(
|
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])
|
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
|
||||||
url = reverse('workouts_view')
|
url = reverse('workouts_view')
|
||||||
# if user.rower.rowerplan == 'freecoach':
|
# if user.rower.rowerplan == 'freecoach':
|
||||||
# url+='?next=/rowers/me/teams'
|
# url+='?next=/rowers/me/teams'
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ from rowers.forms import (
|
|||||||
StravaChartForm, FitnessFitForm, PerformanceManagerForm,
|
StravaChartForm, FitnessFitForm, PerformanceManagerForm,
|
||||||
TrainingPlanBillingForm, InstantPlanSelectForm,
|
TrainingPlanBillingForm, InstantPlanSelectForm,
|
||||||
TrainingZonesForm, InstrokeForm, InStrokeMultipleCompareForm,
|
TrainingZonesForm, InstrokeForm, InStrokeMultipleCompareForm,
|
||||||
ForceCurveMultipleCompareForm, PlanByRscoreForm
|
ForceCurveMultipleCompareForm, PlanByRscoreForm,
|
||||||
|
AssignChoices,
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
@@ -267,6 +268,7 @@ from rowers.tasks import (
|
|||||||
handle_send_email_instantplan_notification,
|
handle_send_email_instantplan_notification,
|
||||||
handle_nk_async_workout,
|
handle_nk_async_workout,
|
||||||
check_tp_workout_id,
|
check_tp_workout_id,
|
||||||
|
handle_assignworkouts,
|
||||||
)
|
)
|
||||||
|
|
||||||
from scipy.signal import savgol_filter
|
from scipy.signal import savgol_filter
|
||||||
|
|||||||
@@ -2031,6 +2031,12 @@ def workouts_bulk_actions(request):
|
|||||||
'Export to {destination} of workout {id} failed'.format(
|
'Export to {destination} of workout {id} failed'.format(
|
||||||
id=encoder.encode_hex(w.id),
|
id=encoder.encode_hex(w.id),
|
||||||
destination=destination))
|
destination=destination))
|
||||||
|
elif action == 'rower assign':
|
||||||
|
assignchoices = AssignChoices(request.POST)
|
||||||
|
if assignchoices.is_valid():
|
||||||
|
remove_workout = assignchoices.cleaned_data['remove_workout']
|
||||||
|
rowers = assignchoices.cleaned_data['destination']
|
||||||
|
_ = myqueue(queuehigh, handle_assignworkouts, workouts, rowers, remove_workout)
|
||||||
url = reverse('workouts_view')
|
url = reverse('workouts_view')
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
@@ -2041,6 +2047,12 @@ def workouts_bulk_actions(request):
|
|||||||
exportchoice = ExportChoices()
|
exportchoice = ExportChoices()
|
||||||
actionform = WorkoutBulkActions()
|
actionform = WorkoutBulkActions()
|
||||||
actionform.fields["action"].initial = action
|
actionform.fields["action"].initial = action
|
||||||
|
assignchoices = AssignChoices()
|
||||||
|
teams = Team.objects.filter(manager=request.user)
|
||||||
|
assignchoices.fields["destination"].queryset = Rower.objects.filter(
|
||||||
|
team__in=teams
|
||||||
|
).distinct().order_by("user__last_name", "user__first_name").exclude(rowerplan='freecoach')
|
||||||
|
assignchoices.fields["destination"].initial = []
|
||||||
form = WorkoutMultipleCompareForm()
|
form = WorkoutMultipleCompareForm()
|
||||||
form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts])
|
form.fields["workouts"].queryset = Workout.objects.filter(id__in=[w.id for w in workouts])
|
||||||
form.fields["workouts"].initial = workouts
|
form.fields["workouts"].initial = workouts
|
||||||
@@ -2049,6 +2061,7 @@ def workouts_bulk_actions(request):
|
|||||||
{'action':action,
|
{'action':action,
|
||||||
'exportchoice':exportchoice,
|
'exportchoice':exportchoice,
|
||||||
'actionform':actionform,
|
'actionform':actionform,
|
||||||
|
'assignchoices': assignchoices,
|
||||||
'form':form,
|
'form':form,
|
||||||
'workouts':workouts})
|
'workouts':workouts})
|
||||||
|
|
||||||
|
|||||||
@@ -90,10 +90,10 @@ INSTALLED_APPS = [
|
|||||||
AUTHENTICATION_BACKENDS = (
|
AUTHENTICATION_BACKENDS = (
|
||||||
#'oauth2_provider.backends.OAuth2Backend',
|
#'oauth2_provider.backends.OAuth2Backend',
|
||||||
# Uncomment following if you want to access the admin
|
# Uncomment following if you want to access the admin
|
||||||
'rules.permissions.ObjectPermissionBackend',
|
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
'django.contrib.auth.backends.RemoteUserBackend',
|
'django.contrib.auth.backends.RemoteUserBackend',
|
||||||
|
'rowers.backends.MyObjectPermissionBackend',
|
||||||
|
#'rules.permissions.ObjectPermissionBackend',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|||||||
Reference in New Issue
Block a user