From 92dc73834263503d9cd746c062fb7078228433dc Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Wed, 16 Oct 2019 09:27:55 +0200
Subject: [PATCH] Add voting form clean and errors

---
 submissions/forms.py                          | 36 +++++++++++++++++--
 .../submissions/pool/recommendation.html      | 22 +++++++++++-
 submissions/views.py                          |  9 +++--
 3 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/submissions/forms.py b/submissions/forms.py
index f1cab22f3..9aeb6fc59 100644
--- a/submissions/forms.py
+++ b/submissions/forms.py
@@ -7,6 +7,7 @@ import re
 
 from django import forms
 from django.conf import settings
+from django.contrib import messages
 # from django.contrib.postgres.search import TrigramSimilarity
 from django.db import transaction
 from django.db.models import Q
@@ -1254,6 +1255,26 @@ class EICRecommendationForm(forms.ModelForm):
         super().__init__(*args, **kwargs)
         self.fields['for_journal'].queryset = Journal.objects.active().filter(
             Q(discipline=self.submission.discipline) | Q(name='SciPost Selections'))
+        self.fields['for_journal'].help_text=(
+            'Please be aware of all the points below!'
+            '<ul><li>SciPost Selections: means article in field flagship journal '
+            '(SciPost Physics, Astronomy, Biology, Chemistry...) '
+            'with extended abstract published separately in SciPost Selections. '
+            'Only choose this for '
+            'an <em>exceptionally</em> good submission to a flagship journal.</li>'
+            '<li>A submission to a flaghip which does not meet the latter\'s '
+            'tough expectations and criteria can be recommended for publication '
+            'in the field\'s Core journal (if it exists).</li>'
+            '<li>Conversely, an extremely good submission to a field\'s Core journal can be '
+            'recommended for publication in the field\'s flagship, provided '
+            'it fulfils the latter\'s expectations and criteria.</li>'
+            '</ul>'
+        )
+        self.fields['recommendation'].help_text=(
+            'Selecting any of the three Publish choices means that you recommend publication.<br>'
+            'Which one you choose simply indicates your ballpark evaluation of the '
+            'submission\'s quality and has no further consequence on the publication.'
+            )
         self.load_assignment()
 
     def save(self):
@@ -1333,17 +1354,28 @@ class RecommendationVoteForm(forms.Form):
     alternative_for_journal = forms.ModelChoiceField(
         label='Alternative recommendation: for which Journal?',
         widget=forms.Select,
-        queryset=Journal.objects.active()
+        queryset=Journal.objects.active(),
+        required=False
     )
     alternative_recommendation = forms.ChoiceField(
         label='Which action do you recommend?',
-        widget=forms.Select, choices=REPORT_REC)
+        widget=forms.Select, choices=REPORT_REC,
+        required=False)
     remark = forms.CharField(widget=forms.Textarea(attrs={
         'rows': 3,
         'cols': 30,
         'placeholder': 'Any further remark you want to add? (optional)'
     }), label='', required=False)
 
+    def clean(self):
+        cleaned_data = super().clean()
+        if (cleaned_data['vote'] == 'disagree' and (
+                cleaned_data['alternative_for_journal'] is None or
+                cleaned_data['alternative_recommendation'] == '')):
+            raise forms.ValidationError(
+                'If you disagree, you must provide an alternative recommendation '
+                '(by filling both the for journal and recommendation fields).')
+
 
 class SubmissionCycleChoiceForm(forms.ModelForm):
     """Make a decision on the Submission's cycle and make publicly available."""
diff --git a/submissions/templates/submissions/pool/recommendation.html b/submissions/templates/submissions/pool/recommendation.html
index ed13a66bc..b3e154c0f 100644
--- a/submissions/templates/submissions/pool/recommendation.html
+++ b/submissions/templates/submissions/pool/recommendation.html
@@ -11,6 +11,26 @@
 {% block pagetitle %}: Editorial Recommendation{% endblock pagetitle %}
 
 {% block content %}
+
+
+  {% if voting_form.errors %}
+    <h1 class="text-danger">Warning: there was an error filling the voting form</h1>
+    {% for field in voting_form %}
+      {% for error in field.errors %}
+        <div class="alert alert-danger">
+          <strong>{{ error|escape }}</strong>
+        </div>
+      {% endfor %}
+    {% endfor %}
+    {% for error in voting_form.non_field_errors %}
+      <div class="alert alert-danger">
+        <strong>{{ error|escape }}</strong>
+      </div>
+    {% endfor %}
+    <p class="text-danger">Please <a href="#votingForm">go back to the form</a> and try again!</p>
+  {% endif %}
+
+
   <h1 class="highlight">Editorial Recommendation to vote on</h1>
 
   <h2>Concerning Submission:</h2>
@@ -155,7 +175,7 @@
   </div>
 
   {% if voting_form %}
-    <h3 class="mt-4">Your position on this recommendation</h3>
+    <h3 class="mt-4" id="votingForm">Your position on this recommendation</h3>
     {% if previous_vote %}
       <p>You had previously voted <span class="text-danger">{{ previous_vote }}</span>; you can use the form below to change your vote and/or add a remark:</p>
     {% endif %}
diff --git a/submissions/views.py b/submissions/views.py
index 8217b5950..4479f4d4c 100644
--- a/submissions/views.py
+++ b/submissions/views.py
@@ -18,6 +18,7 @@ from django.http import Http404, HttpResponse, HttpResponseRedirect
 from django.shortcuts import get_object_or_404, get_list_or_404, render, redirect
 from django.template import Template, Context
 from django.utils import timezone
+from django.utils.safestring import mark_safe
 from django.views.generic.base import RedirectView
 from django.views.generic.detail import SingleObjectMixin, DetailView
 from django.views.generic.edit import CreateView, UpdateView
@@ -1715,13 +1716,14 @@ def vote_on_rec(request, rec_id):
     else:
         form = RecommendationVoteForm(initial=initial)
     if form.is_valid():
+        # Delete previous alternative recs, irrespective of the vote
+        AlternativeRecommendation.objects.filter(
+            eicrec=recommendation, fellow=request.user.contributor).delete()
         if form.cleaned_data['vote'] == 'agree':
             try:
                 recommendation.voted_for.add(request.user.contributor)
             except IntegrityError:
                 messages.warning(request, 'You have already voted for this Recommendation.')
-                #return redirect(reverse('submissions:pool'))
-                pass
             recommendation.voted_against.remove(request.user.contributor)
             recommendation.voted_abstain.remove(request.user.contributor)
         elif form.cleaned_data['vote'] == 'disagree':
@@ -1734,9 +1736,6 @@ def vote_on_rec(request, rec_id):
             # Create an alternative recommendation, if given
             if (form.cleaned_data['alternative_for_journal'] and
                 form.cleaned_data['alternative_recommendation']):
-                # Delete previous alternative recs before creating new one
-                AlternativeRecommendation.objects.filter(
-                    eicrec=recommendation, fellow=request.user.contributor).delete()
                 altrec = AlternativeRecommendation(
                         eicrec=recommendation,
                         fellow=request.user.contributor,
-- 
GitLab