From 03b763de119ce9c6bea3a1266e20cdef9cf84c0a Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 27 Oct 2022 12:01:38 +0200 Subject: [PATCH] switched to template based class --- rowers/interactiveplots.py | 3 +- rowers/urls.py | 23 +++-- rowers/views/analysisviews.py | 165 +++++++++++++++++----------------- rowers/views/statements.py | 5 +- rowsandall_app/urls.py | 2 +- 5 files changed, 110 insertions(+), 88 deletions(-) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 1dcca83f..87a7ec9c 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -4208,7 +4208,8 @@ def forcecurve_multi_interactive_chart(selected): return (script, div) -def instroke_multi_interactive_chart(selected): +def instroke_multi_interactive_chart(selected, *args, **kwargs): + df_plot = pd.DataFrame() ids = [analysis.id for analysis in selected] metrics = list(set([analysis.metric for analysis in selected])) diff --git a/rowers/urls.py b/rowers/urls.py index 63aab31d..5796a45c 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -16,7 +16,7 @@ from rest_framework.urlpatterns import format_suffix_patterns from rest_framework.permissions import * from rowers import views from django.contrib.auth import views as auth_views -from django.views.generic.base import TemplateView +from django.views.generic.base import TemplateView, View from rowers.permissions import ( IsOwnerOrNot, IsOwnerOrReadOnly, @@ -38,6 +38,10 @@ from rowers.serializers import ( PlannedSessionSerializer, ) +from rowers.forms import ForceCurveMultipleCompareForm +from rowers.models import ForceCurveAnalysis +from rowers.interactiveplots import forcecurve_multi_interactive_chart, instroke_multi_interactive_chart + from oauth2_provider.views import ( AuthorizedTokensListView, AuthorizedTokenDeleteView, @@ -836,10 +840,19 @@ urlpatterns = [ re_path(r'^errormessage/(?P[\w\ ]+.*)/$', views.errormessage_view, name='errormessage_view'), re_path(r'^analysis/$', views.analysis_view, name='analysis'), - re_path(r'^analysis/instrokeanalysis/$', views.instrokeanalysis_view, - name='instrokeanalysis_view'), - re_path(r'^analysis/forcecurveanalysis/$', views.forcecurveanalysis_view, - name='forcecurveanalysis_view'), + re_path(r'^analysis/instrokeanalysis/$', views.SavedAnalysisView.as_view( + chart = instroke_multi_interactive_chart, + ), + name='instrokeanalysis_view'), + re_path(r'^analysis/forcecurveanalysis/$', views.SavedAnalysisView.as_view( + template_name='forcecurve_analysis.html', + form_class = ForceCurveMultipleCompareForm, + analysis_class = ForceCurveAnalysis, + chart = forcecurve_multi_interactive_chart, + name = 'Force Curve Analysis', + url = '/rowers/analysis/forcecurveanalysis/' + ), + name='forcecurveanalysis_view'), re_path(r'^analysis/instrokeanalysis/(?P\d+)/delete/$', views.InStrokeAnalysisDelete.as_view(), name='instroke_analysis_delete_view'), re_path(r'^analysis/forcecurveanalysis/(?P\d+)/delete/$', diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 2b67f9dd..ec89755c 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -1844,53 +1844,6 @@ def agegrouprecordview(request, sex='male', weightcategory='hwt', 'the_div': div, }) -@user_passes_test(ispromember, login_url="/rowers/paidplans", - message="This functionality requires a Pro plan or higher." - " If you are already a Pro user, please log in to access this functionality", - redirect_field_name=None) -@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) -def forcecurveanalysis_view(request, userid=0): - r = getrequestrower(request, userid=userid) - - analyses = ForceCurveAnalysis.objects.filter(rower=r).order_by("-date","-id") - selected = [] - - div = "" - script = "" - - - if request.method == 'POST': - form = ForceCurveMultipleCompareForm(request.POST) - - if form.is_valid(): - cd = form.cleaned_data - selected = cd['analyses'] - request.session['analyses'] = [a.id for a in selected] - # now should redirect to analysis - - script, div = forcecurve_multi_interactive_chart(selected) - - - breadcrumbs = [ - { - 'url': '/rowers/analysis', - 'name': 'Analysis' - }, - { - 'url': reverse('instrokeanalysis_view'), - 'name': 'In-Stroke Analysis', - }, - ] - - return render(request, 'forcecurve_analysis.html', - { - 'breadcrumbs': breadcrumbs, - 'analyses': analyses, - 'rower': r, - 'the_script': script, - 'the_div': div, - 'selected': selected, - }) #instroke analysis delete view class ForceCurveAnalysisDelete(DeleteView): @@ -1947,51 +1900,103 @@ class ForceCurveAnalysisDelete(DeleteView): return obj -@user_passes_test(ispromember, login_url="/rowers/paidplans", - message="This functionality requires a Pro plan or higher." - " If you are already a Pro user, please log in to access this functionality", - redirect_field_name=None) -@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True) -def instrokeanalysis_view(request, userid=0): - r = getrequestrower(request, userid=userid) - analyses = InStrokeAnalysis.objects.filter(rower=r).order_by("-date","-id") +class SavedAnalysisView(UserPassesTestMixin, View): + form_class = InStrokeMultipleCompareForm + initial = {} selected = [] - div = "" script = "" + url = '/rowers/analysis/instrokeanalysis/' + name = 'In-Stroke Analysis' + breadcrumbs = [] + + analysis_class = InStrokeAnalysis + template_name = 'instroke_analysis.html' + r = None + analyses = None + chart = instroke_multi_interactive_chart - if request.method == 'POST': - form = InStrokeMultipleCompareForm(request.POST) + def handle_no_permission(self): + if self.request.user.is_anonymous: + url = reverse('login')+'?next='+self.request.path + return HttpResponseRedirect(url) + messages.error(self.request, "This functionality requires a Pro plan or higher." + " If you are already a Pro user, please log in to access this functionality") + return HttpResponseRedirect("/rowers/paidplans") + + + def test_func(self): + return ispromember(self.request.user) + + def __init__(self, *args, **kwargs): + self.userid = kwargs.get('userid',0) + self.form_class = kwargs.get('form_class',self.form_class) + self.initial = kwargs.get('initial', self.initial) + self.selected = kwargs.get('selected', self.selected) + self.name = kwargs.get('name', self.name) + self.url = kwargs.get('url', self.url) + self.analysis_class = kwargs.get('analysis_class', self.analysis_class) + self.template_name = kwargs.get('template_name', self.template_name) + self.chart = kwargs.get('chart', self.chart) + + + self.breadcrumbs = breadcrumbs = [ + { + 'url': '/rowers/analysis', + 'name': 'Analysis' + }, + { + 'url': self.url, + 'name': self.name, + }, + ] + + def setup(self, request, *args, **kwargs): + super(SavedAnalysisView, self).setup(request, *args, **kwargs) + + + self.r = getrequestrower(request, userid=self.userid) + if self.r is not None and not is_coach_user(self.request.user, self.r.user): + raise PermissionDenied("You are not allowed to see analyses for this user") + self.analyses = self.analysis_class.objects.filter(rower=self.r).order_by("-date","-id") + + def get(self, request, *args, **kwargs): + return render(request, self.template_name, + { + 'breadcrumbs': self.breadcrumbs, + 'analyses': self.analyses, + 'rower': self.r, + 'the_script': self.script, + 'the_div': self.div, + 'selected': self.selected, + }) + + def post(self, request, *args, **kwargs): + form = self.form_class(request.POST) if form.is_valid(): cd = form.cleaned_data - selected = cd['analyses'] - request.session['analyses'] = [a.id for a in selected] + self.selected = cd['analyses'] + + request.session['analyses'] = [a.id for a in self.selected] # now should redirect to analysis - script, div = instroke_multi_interactive_chart(selected) + self.script, self.div = self.chart(self.selected) + else: + print(form.errors) + + return render(request, self.template_name, + { + 'breadcrumbs': self.breadcrumbs, + 'analyses': self.analyses, + 'rower': self.r, + 'the_script': self.script, + 'the_div': self.div, + 'selected': self.selected, + }) - breadcrumbs = [ - { - 'url': '/rowers/analysis', - 'name': 'Analysis' - }, - { - 'url': reverse('instrokeanalysis_view'), - 'name': 'In-Stroke Analysis', - }, - ] - return render(request, 'instroke_analysis.html', - { - 'breadcrumbs': breadcrumbs, - 'analyses': analyses, - 'rower': r, - 'the_script': script, - 'the_div': div, - 'selected': selected, - }) #instroke analysis delete view class InStrokeAnalysisDelete(DeleteView): diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 09c5e3b2..036aff86 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -45,7 +45,7 @@ import urllib import yaml from PIL import Image from numbers import Number -from django.views.generic.base import TemplateView +from django.views.generic.base import TemplateView, View from django.contrib.auth import views as auth_views from django.db.models import Q from django import template @@ -119,9 +119,12 @@ from django.urls import reverse, reverse_lazy from django.core.exceptions import PermissionDenied, MultipleObjectsReturned from django.template import RequestContext + from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.conf import settings from django.urls import resolve +from django.utils.decorators import method_decorator +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.utils.datastructures import MultiValueDictKeyError from django.utils import timezone, translation from django.core.mail import send_mail, BadHeaderError diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index 7a9fceb3..76c518fd 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -18,7 +18,7 @@ from django.urls import path, re_path from django.conf import settings from django.conf.urls.static import static from django.contrib import admin -from django.views.generic import TemplateView +from django.views.generic import TemplateView, View from rowsandall_app.views import rootview, landingview, logoview from django.contrib.auth import views as auth_views from rowers import views as rowersviews