From a35161dc4b008efffc2d9737af224aa451acd539 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Wed, 16 Oct 2019 05:20:23 +0200 Subject: [PATCH] Add AlternativeRecommendation for use during voting --- submissions/forms.py | 18 +++++-- .../0070_alternativerecommendation.py | 26 ++++++++++ submissions/models.py | 8 ++++ .../recommendation_author_content.html | 2 +- .../submissions/pool/recommendation.html | 48 ++++++++++++++++++- submissions/views.py | 17 +++++-- 6 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 submissions/migrations/0070_alternativerecommendation.py diff --git a/submissions/forms.py b/submissions/forms.py index 349145ee2..f1cab22f3 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -18,8 +18,10 @@ from .constants import ( REPORT_REFUSAL_CHOICES, STATUS_REJECTED, STATUS_INCOMING, REPORT_POST_EDREC, REPORT_NORMAL, STATUS_DRAFT, STATUS_UNVETTED, REPORT_ACTION_ACCEPT, REPORT_ACTION_REFUSE, STATUS_UNASSIGNED, EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS, SUBMISSION_STATUS, PUT_TO_VOTING, CYCLE_UNDETERMINED, - SUBMISSION_CYCLE_CHOICES, REPORT_PUBLISH_1, REPORT_PUBLISH_2, REPORT_PUBLISH_3, STATUS_VETTED, - REPORT_MINOR_REV, REPORT_MAJOR_REV, REPORT_REJECT, DECISION_FIXED, DEPRECATED, STATUS_COMPLETED, + SUBMISSION_CYCLE_CHOICES, + REPORT_PUBLISH_1, REPORT_PUBLISH_2, REPORT_PUBLISH_3, + REPORT_MINOR_REV, REPORT_MAJOR_REV, REPORT_REJECT, REPORT_REC, + STATUS_VETTED, DECISION_FIXED, DEPRECATED, STATUS_COMPLETED, STATUS_EIC_ASSIGNED, CYCLE_DEFAULT, CYCLE_DIRECT_REC, STATUS_PREASSIGNED, STATUS_REPLACED, STATUS_FAILED_PRESCREENING, STATUS_DEPRECATED, STATUS_ACCEPTED, STATUS_DECLINED, STATUS_WITHDRAWN) from . import exceptions, helpers @@ -1250,7 +1252,7 @@ class EICRecommendationForm(forms.ModelForm): } super().__init__(*args, **kwargs) - self.fields['for_journal'].queryset = Journal.objects.filter( + self.fields['for_journal'].queryset = Journal.objects.active().filter( Q(discipline=self.submission.discipline) | Q(name='SciPost Selections')) self.load_assignment() @@ -1328,10 +1330,18 @@ class RecommendationVoteForm(forms.Form): vote = forms.ChoiceField( widget=forms.RadioSelect, choices=[ ('agree', 'Agree'), ('disagree', 'Disagree'), ('abstain', 'Abstain')]) + alternative_for_journal = forms.ModelChoiceField( + label='Alternative recommendation: for which Journal?', + widget=forms.Select, + queryset=Journal.objects.active() + ) + alternative_recommendation = forms.ChoiceField( + label='Which action do you recommend?', + widget=forms.Select, choices=REPORT_REC) remark = forms.CharField(widget=forms.Textarea(attrs={ 'rows': 3, 'cols': 30, - 'placeholder': 'Your remark (optional)' + 'placeholder': 'Any further remark you want to add? (optional)' }), label='', required=False) diff --git a/submissions/migrations/0070_alternativerecommendation.py b/submissions/migrations/0070_alternativerecommendation.py new file mode 100644 index 000000000..f75270cdd --- /dev/null +++ b/submissions/migrations/0070_alternativerecommendation.py @@ -0,0 +1,26 @@ +# Generated by Django 2.1.8 on 2019-10-15 15:43 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scipost', '0033_auto_20191005_1142'), + ('journals', '0084_journal_minimal_nr_of_reports'), + ('submissions', '0069_auto_20191014_2201'), + ] + + operations = [ + migrations.CreateModel( + name='AlternativeRecommendation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('recommendation', models.SmallIntegerField(choices=[(None, '-'), (1, 'Publish (surpasses expectations and criteria for this Journal; among top 10%)'), (2, 'Publish (easily meets expectations and criteria for this Journal; among top 50%)'), (3, 'Publish (meets expectations and criteria for this Journal)'), (-1, 'Ask for minor revision'), (-2, 'Ask for major revision'), (-3, 'Reject')])), + ('eicrec', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='submissions.EICRecommendation')), + ('fellow', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='scipost.Contributor')), + ('for_journal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='journals.Journal')), + ], + ), + ] diff --git a/submissions/models.py b/submissions/models.py index a91173438..e7b191250 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -1026,6 +1026,14 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): return _str +class AlternativeRecommendation(models.Model): + """Alternative recommendation from voting Fellow who disagrees with EICRec.""" + eicrec = models.ForeignKey('submissions.EICRecommendation', on_delete=models.CASCADE) + fellow = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE) + for_journal = models.ForeignKey('journals.Journal', on_delete=models.CASCADE) + recommendation = models.SmallIntegerField(choices=REPORT_REC) + + class iThenticateReport(TimeStampedModel): """iThenticate report registration. diff --git a/submissions/templates/partials/submissions/recommendation_author_content.html b/submissions/templates/partials/submissions/recommendation_author_content.html index 62d00929d..56dd822c2 100644 --- a/submissions/templates/partials/submissions/recommendation_author_content.html +++ b/submissions/templates/partials/submissions/recommendation_author_content.html @@ -35,7 +35,7 @@ {% block recommendation_before_recommendation %}{% endblock %} <h3 class="pb-0">Recommendation</h3> - <p class="pl-md-3 mb-0"><em>For Journal {{ recommendation.for_journal }}:</em> <strong>{{ recommendation.get_recommendation_display }}</strong></p> + <p class="pl-md-3 mb-0">For Journal <em>{{ recommendation.for_journal }}:</em> <strong>{{ recommendation.get_recommendation_display }}</strong></p> </div> {% if not recommendation.active %} diff --git a/submissions/templates/submissions/pool/recommendation.html b/submissions/templates/submissions/pool/recommendation.html index 6d038c280..ed13a66bc 100644 --- a/submissions/templates/submissions/pool/recommendation.html +++ b/submissions/templates/submissions/pool/recommendation.html @@ -13,7 +13,7 @@ {% block content %} <h1 class="highlight">Editorial Recommendation to vote on</h1> - + <h2>Concerning Submission:</h2> {% include 'partials/submissions/submission_li.html' with submission=recommendation.submission %} <a class="d-inline-block mb-3" href="{{ recommendation.submission.get_absolute_url }}" target="_blank">View Reports and Submission details</a> @@ -57,6 +57,14 @@ {% endfor %} </li> </ul> + {% if old_rec.alternativerecommendation_set.all|length > 0 %} + <h3>Alternative recommendations offered during voting by Fellows who disagreed:</h3> + <ul> + {% for altrec in old_rec.alternativerecommendation_set.all %} + <li>{{ altrec.fellow }}: for Journal <em>{{ altrec.for_journal }}</em>: <strong>{{ altrec.get_recommendation_display }}</strong></li> + {% endfor %} + </ul> + {% endif %} <h3 class="card-title">Remarks:</h3> <ul> {% for rem in old_rec.remarks.all %} @@ -106,6 +114,15 @@ </li> </ul> + {% if recommendation.alternativerecommendation_set.all|length > 0 %} + <h3>Alternative recommendations offered during voting by Fellows who disagreed:</h3> + <ul> + {% for altrec in recommendation.alternativerecommendation_set.all %} + <li>{{ altrec.fellow }}: for Journal <em>{{ altrec.for_journal }}</em>: <strong>{{ altrec.get_recommendation_display }}</strong></li> + {% endfor %} + </ul> + {% endif %} + <h3 class="card-title">Remarks:</h3> <ul> {% for rem in recommendation.remarks.all %} @@ -114,6 +131,7 @@ <li><em>No remarks</em></li> {% endfor %} </ul> + </div> {% if perms.scipost.can_fix_College_decision %} @@ -142,10 +160,36 @@ <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 %} <form action="{% url 'submissions:vote_on_rec' rec_id=recommendation.id %}" method="post"> + <p id="disagree_instructions" class="text-danger"><strong>If you vote disagree, please provide an alternative recommendation below</strong></p> {% csrf_token %} - {{ voting_form|bootstrap:'0,12' }} + {{ voting_form|bootstrap }} <input type="submit" name="submit" value="Cast your vote" class="btn btn-primary" id="submit-id-submit"> </form> {% endif %} {% endblock %} + +{% block footer_script %} + <script nonce="{{ request.csp_nonce }}"> + $(document).ready(function(){ + $("#disagree_instructions").hide() + $("#id_alternative_for_journal").parents('.form-group').hide() + $("#id_alternative_recommendation").parents('.form-group').hide() + $('input[name=vote]').on('change', function(){ + var selection = $('input[name=vote]:checked').val(); + switch(selection){ + case "disagree": + $("#disagree_instructions").show() + $("#id_alternative_for_journal").parents('.form-group').show() + $("#id_alternative_recommendation").parents('.form-group').show() + break; + default: + $("#disagree_instructions").hide() + $("#id_alternative_for_journal").parents('.form-group').hide() + $("#id_alternative_recommendation").parents('.form-group').hide() + break; + } + }).trigger('change'); + }); + </script> +{% endblock %} diff --git a/submissions/views.py b/submissions/views.py index f4b7c5fea..8217b5950 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -29,7 +29,8 @@ from .constants import ( DEPRECATED) from .helpers import check_verified_author, check_unverified_author from .models import ( - Submission, EICRecommendation, EditorialAssignment, RefereeInvitation, Report, SubmissionEvent) + Submission, EICRecommendation, AlternativeRecommendation, + EditorialAssignment, RefereeInvitation, Report, SubmissionEvent) from .mixins import SubmissionAdminViewMixin from .forms import ( SubmissionIdentifierForm, SubmissionForm, SubmissionSearchForm, RecommendationVoteForm, @@ -1729,9 +1730,19 @@ def vote_on_rec(request, rec_id): recommendation.voted_against.add(request.user.contributor) except IntegrityError: messages.warning(request, 'You have already voted against this Recommendation.') - #return redirect(reverse('submissions:pool')) - pass recommendation.voted_abstain.remove(request.user.contributor) + # 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, + for_journal=form.cleaned_data['alternative_for_journal'], + recommendation=form.cleaned_data['alternative_recommendation']) + altrec.save() elif form.cleaned_data['vote'] == 'abstain': recommendation.voted_for.remove(request.user.contributor) recommendation.voted_against.remove(request.user.contributor) -- GitLab