diff --git a/pretalx_musicrate/forms.py b/pretalx_musicrate/forms.py index c6687fb..83d03c1 100644 --- a/pretalx_musicrate/forms.py +++ b/pretalx_musicrate/forms.py @@ -1,7 +1,9 @@ from django import forms +from django.utils.translation import gettext_lazy as _ from django_scopes.forms import SafeModelChoiceField, SafeModelMultipleChoiceField from i18nfield.forms import I18nModelForm from pretalx.person.models import User +from pretalx.submission.forms import SubmissionFilterForm from .models import Assignee, MusicrateSettings, Rating @@ -77,3 +79,7 @@ class AssigneeForm(forms.ModelForm): model = Assignee fields = ("user",) widgets = {"user": forms.Select(attrs={"class": "select2"})} + + +class EnhancedSubmissionFilterForm(SubmissionFilterForm): + require_all_tags = forms.BooleanField(required=False, label=_("require all")) diff --git a/pretalx_musicrate/signals.py b/pretalx_musicrate/signals.py index c9b03db..1231531 100644 --- a/pretalx_musicrate/signals.py +++ b/pretalx_musicrate/signals.py @@ -24,10 +24,20 @@ def pretalx_musicrate_placeholders(sender, **kwargs): @receiver(nav_event) -def pretalx_musicrate_qrcode(sender, request, **kwargs): +def pretalx_musicrate_nav_event(sender, request, **kwargs): if not request.user.has_perm("orga.view_submissions", request.event): return [] return [ + { + "active": request.resolver_match.view_name + == "plugins:pretalx_musicrate:enhanced_list", + "icon": "sticky-note-o", + "label": _("Proposals, but better"), + "url": reverse( + "plugins:pretalx_musicrate:enhanced_list", + kwargs={"event": request.event.slug}, + ), + }, { "active": request.resolver_match.view_name == "plugins:pretalx_musicrate:qrcode", @@ -36,7 +46,7 @@ def pretalx_musicrate_qrcode(sender, request, **kwargs): "url": reverse( "plugins:pretalx_musicrate:qrcode", kwargs={"event": request.event.slug} ), - } + }, ] diff --git a/pretalx_musicrate/static/pretalx_musicrate/submission_filter.js b/pretalx_musicrate/static/pretalx_musicrate/submission_filter.js new file mode 100644 index 0000000..18b7d4d --- /dev/null +++ b/pretalx_musicrate/static/pretalx_musicrate/submission_filter.js @@ -0,0 +1,11 @@ +document.addEventListener("DOMContentLoaded", function() { + const updateRequireAllVisibility = () => { + if (document.querySelector("#id_tags").value) { + document.querySelector("#requireAll").classList.remove("d-none") + } else { + document.querySelector("#requireAll").classList.add("d-none") + } + } + $("#id_tags").on("change", updateRequireAllVisibility) + updateRequireAllVisibility() +}) diff --git a/pretalx_musicrate/templates/pretalx_musicrate/enhanced_list.html b/pretalx_musicrate/templates/pretalx_musicrate/enhanced_list.html new file mode 100644 index 0000000..fe20d1f --- /dev/null +++ b/pretalx_musicrate/templates/pretalx_musicrate/enhanced_list.html @@ -0,0 +1,154 @@ +{% extends "orga/base.html" %} +{% load bootstrap4 %} +{% load compress %} +{% load i18n %} +{% load rules %} +{% load static %} +{% load url_replace %} + +{% block scripts %} + {% compress js %} + + {% endcompress %} + {% compress js %} + + {% endcompress %} +{% endblock %} + +{% block content %} + {% has_perm 'orga.change_submission_state' request.user request.event as can_change_submission %} + {% has_perm 'orga.view_speakers' request.user request.event as can_view_speakers %} +
+ + {% blocktranslate trimmed with question=filter_form.cleaned_data.question.question %} + List filtered by answers to question "{{ question }}". + {% endblocktranslate %} + + + {% translate "Remove filter" %} + +
+ {% endif %} ++ {% translate "Rating" %} + + + | ++ {% translate "Title" %} + + + | + {% if show_submission_types %} ++ {% translate "Type" %} + | + {% endif %} ++ {% translate "State" %} + + + | ++ {% translate "Assignee" %} + + + | + {% if can_change_submission %} ++ {% endif %} + |
---|---|---|---|---|---|
+ {% if submission.rating %} + {{ submission.rating.value }} + {% else %} + – + {% endif %} + | ++ + {% if can_view_speakers %}{{ submission.title }}{% else %}{{ submission.anonymised.title|default:submission.title }}{% endif %} + + | + {% if show_submission_types %} ++ {{ submission.submission_type.name }} + | + {% endif %} ++ {% include "orga/submission/state_dropdown.html" with submission=submission %} + | ++ {% if submission.assignee %} + {{ submission.assignee.user.name }} + {% else %} + – + {% endif %} + {% if can_change_submission %} + + + + {% endif %} + | + {% if can_change_submission %} ++ + + + + + + | + {% endif %} +
/", AssigneeView.as_view(), name="assignee"),
]
),
diff --git a/pretalx_musicrate/views.py b/pretalx_musicrate/views.py
index e94a88e..cdef06a 100644
--- a/pretalx_musicrate/views.py
+++ b/pretalx_musicrate/views.py
@@ -15,9 +15,15 @@ from django.views.generic import FormView, TemplateView, View
from django.views.generic.detail import SingleObjectMixin
from django_context_decorator import context
from pretalx.common.mixins.views import EventPermissionRequired
+from pretalx.orga.views.submission import SubmissionList
from pretalx.submission.models import Submission
-from .forms import AssigneeForm, MusicrateSettingsForm, RatingForm
+from .forms import (
+ AssigneeForm,
+ EnhancedSubmissionFilterForm,
+ MusicrateSettingsForm,
+ RatingForm,
+)
from .models import Juror, Rating
youtube_re = re.compile(
@@ -470,3 +476,23 @@ class AssigneeView(EventPermissionRequired, FormView, SingleObjectMixin):
def post(self, *args, **kwargs):
self.object = self.get_object()
return super().post(*args, **kwargs)
+
+
+class EnhancedSubmissionList(SubmissionList):
+ sortable_fields = ("code", "rating", "title", "state", "assignee")
+ template_name = "pretalx_musicrate/enhanced_list.html"
+
+ def get_filter_form(self):
+ return EnhancedSubmissionFilterForm(
+ data=self.request.GET,
+ event=self.request.event,
+ usable_states=self.usable_states,
+ limit_tracks=self.limit_tracks,
+ )
+
+ def filter_queryset(self, qs):
+ qs = super().filter_queryset(qs.prefetch_related("assignee"))
+ if self.request.GET.get("require_all_tags", "") == "on":
+ for tag in self.request.GET.getlist("tags"):
+ qs = qs.filter(tags__in=[tag])
+ return qs