diff --git a/doc/changelog.rst b/doc/changelog.rst index e58d9e96f..6c27208bf 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -3,6 +3,7 @@ Release Notes ============= +- :bug:`orga:review` Assigning reviewers could lead to incorrect assignments when browsers cached the form, but new reviewers were added to the team, shifting the overall order of input fields. - :feature:`cfp` Choice and multiple choice questions now use a drop-down with typeahead (search for options) when they have a lot of options. - :feature:`orga,1079` All images in forms in the organiser area now include a preview of the saved image, and open a lightbox instead of the image file when clicked. - :announcement:`admin` We now recommend that you use a virtualenv instead of the ``pip --user`` installation method, and have updated our install and upgrade documentation accordingly. diff --git a/src/pretalx/orga/forms/review.py b/src/pretalx/orga/forms/review.py index 6f34dea92..a31e6b308 100644 --- a/src/pretalx/orga/forms/review.py +++ b/src/pretalx/orga/forms/review.py @@ -183,57 +183,56 @@ class DirectionForm(forms.Form): ) -class ReviewerForProposalForm(forms.ModelForm): - def __init__(self, *args, reviewers=None, **kwargs): +class ReviewAssignmentForm(forms.Form): + def __init__(self, *args, event=None, **kwargs): + self.event = event + self.reviewers = ( + User.objects.filter(teams__in=self.event.teams.filter(is_reviewer=True)) + .order_by("name") + .distinct() + ).prefetch_related("assigned_reviews") + self.submissions = self.event.submissions.order_by("title").prefetch_related( + "assigned_reviewers" + ) super().__init__(*args, **kwargs) - self.fields["assigned_reviewers"].queryset = reviewers - self.fields["assigned_reviewers"].label = self.instance.title - def save(self, *args, **kwargs): - # No calling 'super().save()' here – it would potentially update a submission's code! - instance = self.instance - if "assigned_reviewers" in self.changed_data: - new_code = self.cleaned_data.get("code") - if instance.code != new_code: - instance = instance.event.submissions.all().get(code=new_code) - instance.assigned_reviewers.set(self.cleaned_data["assigned_reviewers"]) - class Meta: - model = Submission - fields = ["assigned_reviewers", "code"] - widgets = { - "assigned_reviewers": forms.SelectMultiple(attrs={"class": "select2"}), - "code": forms.HiddenInput(), - } +class ReviewerForProposalForm(ReviewAssignmentForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + review_choices = [(r.id, r.name) for r in self.reviewers] + for submission in self.submissions: + self.fields[submission.code] = forms.MultipleChoiceField( + choices=review_choices, + widget=forms.SelectMultiple(attrs={"class": "select2"}), + initial=list( + submission.assigned_reviewers.values_list("id", flat=True) + ), + label=submission.title, + required=False, + ) + + def save(self, *args, **kwargs): + for submission in self.submissions: + submission.assigned_reviewers.set(self.cleaned_data[submission.code]) -class ProposalForReviewerForm(forms.ModelForm): - def __init__(self, *args, proposals=None, **kwargs): +class ProposalForReviewerForm(ReviewAssignmentForm): + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - initial = proposals.filter(assigned_reviewers__in=[self.instance]).values_list( - "id", flat=True - ) - self.fields["assigned_reviews"] = forms.MultipleChoiceField( - choices=((p.id, p.title) for p in proposals), - widget=forms.SelectMultiple(attrs={"class": "select2"}), - label=self.instance.name, - initial=list(initial), - required=False, - ) + submission_choices = [(s.id, s.title) for s in self.submissions] + for reviewer in self.reviewers: + self.fields[reviewer.code] = forms.MultipleChoiceField( + choices=submission_choices, + widget=forms.SelectMultiple(attrs={"class": "select2"}), + initial=list(reviewer.assigned_reviews.values_list("id", flat=True)), + label=reviewer.name, + required=False, + ) def save(self, *args, **kwargs): - # No calling 'super().save()' here – it would potentially update a user's code! - instance = self.instance - if "assigned_reviews" in self.changed_data: - new_code = self.cleaned_data.get("code") - if instance.code != new_code: - instance = User.objects.get(code=new_code) - instance.assigned_reviews.set(self.cleaned_data["assigned_reviews"]) - - class Meta: - model = User - fields = ["code"] - widgets = {"code": forms.HiddenInput()} + for reviewer in self.reviewers: + reviewer.assigned_reviews.set(self.cleaned_data[reviewer.code]) class ReviewExportForm(ExportForm): diff --git a/src/pretalx/orga/templates/orga/review/assignment.html b/src/pretalx/orga/templates/orga/review/assignment.html index 8f9ebd554..56ffda572 100644 --- a/src/pretalx/orga/templates/orga/review/assignment.html +++ b/src/pretalx/orga/templates/orga/review/assignment.html @@ -2,13 +2,10 @@ {% load bootstrap4 %} {% load compress %} {% load i18n %} -{% load formset_tags %} {% load static %} {% block content %} {% compress js %} - - {% endcompress %}