pretalx-musicrate/pretalx_musicrate/views.py

192 lines
5.7 KiB
Python

from hmac import compare_digest
from operator import itemgetter
from django.contrib import messages
from django.db.models import F, Max, Min, Window
from django.db.models.functions import RowNumber
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView, TemplateView
from django.views.generic.detail import SingleObjectMixin
from django_context_decorator import context
from pretalx.common.mixins.views import EventPermissionRequired
from .forms import MusicrateSettingsForm
class JoinView(TemplateView):
template_name = "pretalx_musicrate/join.html"
def validate_token(self, token):
if compare_digest(
token.encode("utf-8"),
self.request.event.pretalx_musicrate_settings.join_token.encode("utf-8"),
):
return True
messages.error(self.request, _("Invalid token"))
return False
def get_context_data(self, token_valid=False, **kwargs):
context = super().get_context_data(**kwargs)
context["token_valid"] = token_valid
return context
def get(self, request, *args, token, **kwargs):
token_valid = self.validate_token(token)
return super().get(request, *args, token_valid=token_valid, **kwargs)
def post(self, request, *args, token, **kwargs):
token_valid = self.validate_token(token)
if token_valid:
return redirect(request.path)
return self.render_to_response(
self.get_context_data(token_valid=token_valid, **kwargs)
)
class MusicrateSettingsView(EventPermissionRequired, FormView):
permission_required = "orga.change_settings"
template_name = "pretalx_musicrate/settings.html"
form_class = MusicrateSettingsForm
def get_success_url(self):
return self.request.path
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["event"] = self.request.event
return kwargs
def form_valid(self, form):
form.save()
messages.success(
self.request, _("The pretalx-musicrate settings were updated.")
)
return super().form_valid(form)
class QRCodeView(EventPermissionRequired, TemplateView):
permission_required = "orga.view_submissions"
template_name = "pretalx_musicrate/qrcode.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["contents"] = self.request.build_absolute_uri(
reverse(
"plugins:pretalx_musicrate:join",
kwargs={
"event": self.request.event.slug,
"token": self.request.event.pretalx_musicrate_settings.join_token,
},
)
)
return context
class SubmissionMixin(SingleObjectMixin):
slug_field = "code"
slug_url_kwarg = "code"
def get_queryset(self):
return self.request.event.submissions.prefetch_related("answers").filter(
submission_type__in=self.request.event.pretalx_musicrate_settings.submission_types.all()
)
@context
@cached_property
def submission(self):
return self.get_object()
@context
@cached_property
def genre(self):
return (
self.submission.answers.filter(
question=self.request.event.pretalx_musicrate_settings.genre_question
)
.values_list("answer", flat=True)
.first()
)
@context
@cached_property
def origin(self):
return (
self.submission.answers.filter(
question=self.request.event.pretalx_musicrate_settings.origin_question
)
.values_list("answer", flat=True)
.first()
)
def get_url_kwargs(self, **kwargs):
return self.request.resolver_match.kwargs | kwargs
@context
@cached_property
def prev(self):
prev = (
self.get_queryset()
.annotate(prev=Max("created"))
.filter(created__lt=self.submission.created, created=F("prev"))
.first()
)
if prev is None:
return None
return reverse(
self.request.resolver_match.view_name,
kwargs=self.get_url_kwargs(code=prev.code),
)
@context
@cached_property
def index(self):
return next(
map(
itemgetter(1),
filter(
lambda s: s[0] == self.submission.pk,
self.get_queryset()
.annotate(index=Window(expression=RowNumber(), order_by="created"))
.values_list("pk", "index"),
),
)
)
@context
@cached_property
def count(self):
return self.get_queryset().count()
@context
@cached_property
def next(self):
next = (
self.get_queryset()
.annotate(next=Min("created"))
.filter(created__gt=self.submission.created, created=F("next"))
.first()
)
if next is None:
return None
return reverse(
self.request.resolver_match.view_name,
kwargs=self.get_url_kwargs(code=next.code),
)
class PresenterView(EventPermissionRequired, SubmissionMixin, TemplateView):
permission_required = "orga.view_submissions"
template_name = "pretalx_musicrate/present.html"
@context
@property
def can_continue(self):
return True
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, *args, **kwargs)