feat: add presenter view
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Luca 2023-12-15 17:12:12 +01:00
parent bdd03fa015
commit e070fd1281
5 changed files with 174 additions and 1 deletions

View File

@ -0,0 +1,4 @@
{% extends "pretalx_musicrate/submission_base.html" %}
{% block submission_content %}
{% endblock %}

View File

@ -0,0 +1,55 @@
{% extends "cfp/event/base.html" %}
{% load compress %}
{% load i18n %}
{% block title %}{{ submission.title }} ::{% endblock %}
{% block cfp_header %}
{% compress css %}
<style>
.musicrate-pagination {
display: flex;
}
.musicrate-pagination > * {
flex-basis: 0;
}
.musicrate-pagination > a {
flex-grow: 1;
}
.musicrate-pagination > a:last-child {
text-align: right;
}
</style>
{% endcompress %}
{% block submission_header %}
{% endblock %}
{% endblock %}
{% block content %}
{% translate "(not specified)" as not_specified %}
<h1>{{ submission.title }}</h1>
<p>
{{ genre|default:not_specified }} &middot; {{ origin|default:not_specified }}
{% if submission.internal_notes %}
<br>
{{ submission.internal_notes }}
{% endif %}
</p>
{% block submission_content %}
{% endblock %}
<div class="musicrate-pagination">
{% if prev %}
<a href="{{ prev }}">&lt; {% translate "Previous" %}</a>
{% else %}
<a></a>
{% endif %}
{% if index and count %}
{{ index }}/{{ count }}
{% endif %}
{% if next and can_continue %}
<a href="{{ next }}">{% translate "Next" %} &gt;</a>
{% else %}
<a></a>
{% endif %}
</div>
{% endblock %}

View File

@ -1,6 +1,6 @@
from django.urls import include, path from django.urls import include, path
from .views import JoinView, MusicrateSettingsView, QRCodeView from .views import JoinView, MusicrateSettingsView, PresenterView, QRCodeView
urlpatterns = [ urlpatterns = [
path( path(
@ -13,6 +13,7 @@ urlpatterns = [
include( include(
[ [
path("", QRCodeView.as_view(), name="qrcode"), path("", QRCodeView.as_view(), name="qrcode"),
path("present/<code>/", PresenterView.as_view(), name="present"),
path("<slug:token>/", JoinView.as_view(), name="join"), path("<slug:token>/", JoinView.as_view(), name="join"),
] ]
), ),

View File

@ -1,10 +1,16 @@
from hmac import compare_digest from hmac import compare_digest
from operator import itemgetter
from django.contrib import messages 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.shortcuts import redirect
from django.urls import reverse from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView, TemplateView 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 pretalx.common.mixins.views import EventPermissionRequired
from .forms import MusicrateSettingsForm from .forms import MusicrateSettingsForm
@ -77,3 +83,109 @@ class QRCodeView(EventPermissionRequired, TemplateView):
) )
) )
return context 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)

View File

@ -14,6 +14,7 @@ maintainers = [
dependencies = [ dependencies = [
"Django", "Django",
"django-context-decorator",
"django-i18nfield", "django-i18nfield",
"pretalx", "pretalx",
"qrcode", "qrcode",