feat: implement enhanced submission list
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
d709f020f4
commit
ca3ca52ab2
|
@ -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"))
|
||||
|
|
|
@ -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}
|
||||
),
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
})
|
|
@ -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 %}
|
||||
<script src="{% static "orga/js/submission_filter.js" %}"></script>
|
||||
{% endcompress %}
|
||||
{% compress js %}
|
||||
<script src="{% static "pretalx_musicrate/submission_filter.js" %}"></script>
|
||||
{% 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 %}
|
||||
<h2>
|
||||
{{ page_obj.paginator.count }}
|
||||
{% blocktranslate trimmed count count=page_obj.paginator.count %}
|
||||
proposal
|
||||
{% plural %}
|
||||
proposals
|
||||
{% endblocktranslate %}
|
||||
</h2>
|
||||
|
||||
<div class="submit-group search-submit-group">
|
||||
<form class="search-form">
|
||||
{% bootstrap_form search_form %}
|
||||
{% if show_submission_types and filter_form.submission_type %}{% bootstrap_field filter_form.submission_type %}{% endif %}
|
||||
<div class="d-flex flex-column form-group">
|
||||
{% bootstrap_field filter_form.state layout='inline' %}
|
||||
<div id="pending" class="d-none">{% bootstrap_field filter_form.pending_state__isnull layout='inline' %}</div>
|
||||
</div>
|
||||
{% if filter_form.track %}{% bootstrap_field filter_form.track %}{% endif %}
|
||||
{% if filter_form.tags %}
|
||||
<div class="d-flex flex-column form-group">
|
||||
{% bootstrap_field filter_form.tags layout='inline' %}
|
||||
<div id="requireAll" class="d-none">{% bootstrap_field filter_form.require_all_tags layout='inline' %}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if filter_form.content_locale %}{% bootstrap_field filter_form.content_locale %}{% endif %}
|
||||
<button class="btn btn-success" type="submit">{% translate "Search" %}</button>
|
||||
</form>
|
||||
{% if filter_form.is_valid and filter_form.cleaned_data.question %}
|
||||
<p class="text-muted ml-2">
|
||||
<span class="fa fa-filter"></span>
|
||||
{% blocktranslate trimmed with question=filter_form.cleaned_data.question.question %}
|
||||
List filtered by answers to question "{{ question }}".
|
||||
{% endblocktranslate %}
|
||||
<a href="?{% url_replace request 'question' '' 'answer' '' 'answer__options' '' %}" class="text-muted">
|
||||
<span class="fa fa-times"></span>
|
||||
{% translate "Remove filter" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover table-flip">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
{% translate "Rating" %}
|
||||
<a href="?{% url_replace request 'sort' 'rating' %}"><i class="fa fa-caret-down" title="{% translate "Sort by rating (10-0)" %}"></i></a>
|
||||
<a href="?{% url_replace request 'sort' '-rating' %}"><i class="fa fa-caret-up" title="{% translate "Sort by rating (0-10)" %}"></i></a>
|
||||
</th>
|
||||
<th>
|
||||
{% translate "Title" %}
|
||||
<a href="?{% url_replace request 'sort' 'title' %}"><i class="fa fa-caret-down" title="{% translate "Sort by title (a-z)" %}"></i></a>
|
||||
<a href="?{% url_replace request 'sort' '-title' %}"><i class="fa fa-caret-up" title="{% translate "Sort by title (z-a)" %}"></i></a>
|
||||
</th>
|
||||
{% if show_submission_types %}
|
||||
<th>
|
||||
{% translate "Type" %}
|
||||
</th>
|
||||
{% endif %}
|
||||
<th>
|
||||
{% translate "State" %}
|
||||
<a href="?{% url_replace request 'sort' 'state' %}"><i class="fa fa-caret-down" title="{% translate "Sort by state (a-z)" %}"></i></a>
|
||||
<a href="?{% url_replace request 'sort' '-state' %}"><i class="fa fa-caret-up" title="{% translate "Sort by state (z-a)" %}"></i></a>
|
||||
</th>
|
||||
<th>
|
||||
{% translate "Assignee" %}
|
||||
<a href="?{% url_replace request 'sort' 'assignee' %}"><i class="fa fa-caret-down" title="{% translate "Sort by assignee (a-z)" %}"></i></a>
|
||||
<a href="?{% url_replace request 'sort' '-assignee' %}"><i class="fa fa-caret-up" title="{% translate "Sort by assignee (z-a)" %}"></i></a>
|
||||
</th>
|
||||
{% if can_change_submission %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for submission in submissions %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if submission.rating %}
|
||||
{{ submission.rating.value }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ submission.orga_urls.base }}">
|
||||
{% if can_view_speakers %}{{ submission.title }}{% else %}{{ submission.anonymised.title|default:submission.title }}{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
{% if show_submission_types %}
|
||||
<td>
|
||||
{{ submission.submission_type.name }}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{% include "orga/submission/state_dropdown.html" with submission=submission %}
|
||||
</td>
|
||||
<td>
|
||||
{% if submission.assignee %}
|
||||
{{ submission.assignee.user.name }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
{% if can_change_submission %}
|
||||
<a class="btn btn-sm btn-link"
|
||||
href="{% url "plugins:pretalx_musicrate:assignee" event=request.event.slug code=submission.code %}"
|
||||
title="{% translate "edit" %}">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if can_change_submission %}
|
||||
<td class="action-column">
|
||||
<a href="{{ submission.orga_urls.edit }}"
|
||||
title="{% translate "edit" %}"
|
||||
class="btn btn-sm btn-info">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
<a href="{{ submission.orga_urls.delete }}?from=list"
|
||||
title="{% translate "Delete" %}"
|
||||
class="btn btn-sm btn-danger">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% include "orga/pagination.html" %}
|
||||
{% endblock %}
|
|
@ -2,6 +2,7 @@ from django.urls import include, path
|
|||
|
||||
from .views import (
|
||||
AssigneeView,
|
||||
EnhancedSubmissionList,
|
||||
ExportView,
|
||||
JoinView,
|
||||
MayAdvanceView,
|
||||
|
@ -26,6 +27,11 @@ urlpatterns = [
|
|||
include(
|
||||
[
|
||||
path("export/", ExportView.as_view(), name="export"),
|
||||
path(
|
||||
"list/",
|
||||
EnhancedSubmissionList.as_view(),
|
||||
name="enhanced_list",
|
||||
),
|
||||
path("<code>/", AssigneeView.as_view(), name="assignee"),
|
||||
]
|
||||
),
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue