feat: add presenter view
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
bdd03fa015
commit
e070fd1281
|
@ -0,0 +1,4 @@
|
||||||
|
{% extends "pretalx_musicrate/submission_base.html" %}
|
||||||
|
|
||||||
|
{% block submission_content %}
|
||||||
|
{% endblock %}
|
|
@ -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 }} · {{ 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 }}">< {% translate "Previous" %}</a>
|
||||||
|
{% else %}
|
||||||
|
<a></a>
|
||||||
|
{% endif %}
|
||||||
|
{% if index and count %}
|
||||||
|
{{ index }}/{{ count }}
|
||||||
|
{% endif %}
|
||||||
|
{% if next and can_continue %}
|
||||||
|
<a href="{{ next }}">{% translate "Next" %} ></a>
|
||||||
|
{% else %}
|
||||||
|
<a></a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -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"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -14,6 +14,7 @@ maintainers = [
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Django",
|
"Django",
|
||||||
|
"django-context-decorator",
|
||||||
"django-i18nfield",
|
"django-i18nfield",
|
||||||
"pretalx",
|
"pretalx",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
|
|
Loading…
Reference in New Issue