diff --git a/journals/templates/journals/sign_existing_report.html b/journals/templates/journals/sign_existing_report.html index 99b8db35f47f12abc642bc14ddad4f0b96eb5a78..422659cd787f3887bd2c3ca8d230a118a83a33f1 100644 --- a/journals/templates/journals/sign_existing_report.html +++ b/journals/templates/journals/sign_existing_report.html @@ -4,30 +4,46 @@ {% block pagetitle %}: sign existing Report{% endblock pagetitle %} +{% block breadcrumb %} +<div class="container-outside breadcrumb-nav"> + <div class="container"> + <nav class="breadcrumb"> + <a href="{% url 'submissions:submissions' %}" class="breadcrumb-item">Submissions</a> + <a href="{{ report.submission.get_absolute_url }}" class="breadcrumb-item">{{ report.submission.arxiv_identifier_w_vn_nr }}</a> + <span class="breadcrumb-item">Sign existing Report</span> + + </nav> + </div> +</div> +{% endblock %} + {% block content %} <div class="row"> - <div class="col-12"> - <hr class="hr12"> - <div class="row"> - <div class="col-6"> - <h2>Confirmation page: do you wish to sign this Report?</h2> - <h3>(your Report is reproduced below for your convenience)</h3> - </div> - <div class="col-6"> - <form action="{% url 'journals:sign_existing_report' report_id=report.id %}" method="post"> - {% csrf_token %} - {{ form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Submit" /> - </form> - </div> + <div class="col-12"> + <h1 class="highlight">Sign existing Report</h1> </div> +</div> - <h3>Report on Submission <a href="{{report.submission.get_absolute_url}}">{{report.submission.title}}</a></h3> - - {% include 'submissions/_single_public_report_without_comments.html' with report=report user=request.user perms=perms %} +<div class="row"> + <div class="col-md-6"> + <h2>Confirmation page: do you wish to sign this Report?</h2> + <h3>(your Report is reproduced below for your convenience)</h3> + </div> + <div class="col-md-6"> + <form action="{% url 'journals:sign_existing_report' report_id=report.id %}" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-secondary" type="submit" value="Submit" /> + </form> + </div> +</div> - </div> +<div class="row"> + <div class="col-12"> + <h3>Report on Submission <a href="{{report.submission.get_absolute_url}}">{{report.submission.title}}</a></h3> + {% include 'submissions/_single_public_report_without_comments.html' with report=report user=request.user perms=perms %} + </div> </div> {% endblock %} diff --git a/scipost/static/scipost/assets/config/preconfig.scss b/scipost/static/scipost/assets/config/preconfig.scss index c6a977bfc80f6313bf2b4b00941ba3a0ad0f4b30..1b63ae443e707898ce0c398eb5b31207427fe7d6 100644 --- a/scipost/static/scipost/assets/config/preconfig.scss +++ b/scipost/static/scipost/assets/config/preconfig.scss @@ -17,13 +17,6 @@ $alert-padding-x: 0.75rem; // Grid // $grid-gutter-width: 20px; -// $container-max-widths: ( -// xs: , -// sm: 728px, -// md: 720px, -// lg: 960px, -// xl: 1140px -// ); // Colors // @@ -66,7 +59,7 @@ $alert-border-radius: $base-border-radius; // Cards // $card-border-radius: $base-border-radius; -$card-bg: $gray-200; +$card-bg: $white; $card-border-color: $gray-200; $card-spacer-x: 0.75rem; $card-spacer-y: 0.5rem; diff --git a/scipost/static/scipost/assets/css/_list_group.scss b/scipost/static/scipost/assets/css/_list_group.scss index 4755ec289813f41a3be705df5c68db980d203c26..fda5fa2d7c7d4f0cbe84677eff66e8cf0a505092 100644 --- a/scipost/static/scipost/assets/css/_list_group.scss +++ b/scipost/static/scipost/assets/css/_list_group.scss @@ -23,3 +23,7 @@ ul.events-list { } } } + +.fa-li { + line-height: 1.25 !important; +} diff --git a/submissions/forms.py b/submissions/forms.py index ee1365c2b8033b8aca7292f66a0cee41ed5facb5..d313ebc7be05815bdf28d9f9f110c6ba5206692e 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -594,10 +594,9 @@ class ReportForm(forms.ModelForm): report.status = STATUS_UNVETTED # Update invitation and report meta data if exist - invitation = submission.referee_invitations.filter(referee=report.author).first() - if invitation: - invitation.fulfilled = True - invitation.save() + updated_invitations = submission.referee_invitations.filter( + referee=report.author).update(fulfilled=True) + if updated_invitations > 0: report.invited = True # Check if report author if the report is being flagged on the submission diff --git a/submissions/managers.py b/submissions/managers.py index 021daa46a5a214d085a4a1faa3ba7890e14b3ff7..7ae6a6f4e59959df85f9e8907cdbb96106e3ddc3 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -320,6 +320,9 @@ class ReportQuerySet(models.QuerySet): class RefereeInvitationQuerySet(models.QuerySet): + def awaiting_response(self): + return self.pending().open() + def pending(self): return self.filter(accepted=None) diff --git a/submissions/models.py b/submissions/models.py index 5a526bf214336075cb7e142fe344827efa6a0f59..40e381f2c87fcb42b64abf3f4809bf70e37f695b 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -14,7 +14,8 @@ from .constants import ASSIGNMENT_REFUSAL_REASONS, ASSIGNMENT_NULLBOOL,\ RANKING_CHOICES, REPORT_REC, SUBMISSION_STATUS, STATUS_UNASSIGNED,\ REPORT_STATUSES, STATUS_UNVETTED, SUBMISSION_EIC_RECOMMENDATION_REQUIRED,\ SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC,\ - EVENT_GENERAL, EVENT_TYPES, EVENT_FOR_AUTHOR, EVENT_FOR_EIC + EVENT_GENERAL, EVENT_TYPES, EVENT_FOR_AUTHOR, EVENT_FOR_EIC,\ + STATUS_DRAFT, STATUS_VETTED from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationQuerySet,\ ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet from .utils import ShortSubmissionCycle, DirectRecommendationSubmissionCycle,\ @@ -360,6 +361,10 @@ class RefereeInvitation(SubmissionRelatedObjectMixin, models.Model): def notification_name(self): return self.submission.arxiv_identifier_w_vn_nr + @property + def related_report(self): + return self.submission.reports.filter(author=self.referee).first() + def reset_content(self): self.nr_reminders = 0 self.date_last_reminded = None @@ -452,6 +457,14 @@ class Report(SubmissionRelatedObjectMixin, models.Model): return (self.author.user.first_name + ' ' + self.author.user.last_name + ' on ' + self.submission.title[:50] + ' by ' + self.submission.author_list[:50]) + @property + def is_in_draft(self): + return self.status == STATUS_DRAFT + + @property + def is_vetted(self): + return self.status == STATUS_VETTED + def save(self, *args, **kwargs): # Control Report count per Submission. if not self.report_nr: diff --git a/submissions/templates/partials/submissions/refereeing_status_card.html b/submissions/templates/partials/submissions/refereeing_status_card.html new file mode 100644 index 0000000000000000000000000000000000000000..c2f69c2db34d4096eae3b91ea24d68ce8d8964bb --- /dev/null +++ b/submissions/templates/partials/submissions/refereeing_status_card.html @@ -0,0 +1,73 @@ + +<div class="card"> + <div class="card-body"> + {% if invitation.accepted is None %} + <h3 class="card-title">Referee Invitation response pending</h3> + <p class="card-text"> + In view of your expertise and on behalf of the Editor-in-charge we would like to invite you to referee this Submission. Please accept or decline this invitation. + We would be extremely grateful for your contribution, and thank you in advance for your consideration. + </p> + <a href="{% url 'submissions:accept_or_decline_ref_invitations' invitation.id %}" class="card-link">Accept or decline here</a> + {% elif invitation.accepted %} + <h3 class="card-title">Referee Invitation</h3> + <p class="card-text">Thank you for agreeing to referee this Submission. The following checklist will help you finish your refereeing task.</p> + <ul class="fa-ul"> + <li><i class="fa-li fa fa-check-square-o"></i>Accepted Invitation.</li> + + <li> + {% if invitation.fulfilled %} + <i class="fa-li fa fa-check-square-o"></i>Submitted Report on {{ invitation.related_report.date_submitted }}. + {% else %} + <i class="fa-li fa fa-square-o"></i> + {% if invitation.related_report.is_in_draft %} + You have a Report in draft, <a href="{% url 'submissions:submit_report' invitation.submission.arxiv_identifier_w_vn_nr %}">finish your Report</a>. + {% else %} + <a href="{% url 'submissions:submit_report' invitation.submission.arxiv_identifier_w_vn_nr %}">Submit your Report</a>. + {% endif %} + {% endif %} + </li> + <li> + {% if invitation.related_report.is_vetted %} + <i class="fa-li fa fa-check-square-o"></i>Report vetted by Editor-in-charge. + {% else %} + <i class="fa-li fa fa-square-o"></i>Report vetted by Editor-in-charge. + {% endif %} + </li> + </ul> + + {% if invitation.related_report.is_vetted %} + {% if invitation.related_report.anonymous %} + <p class="card-text">You have anonymously submitted your Report. <a href="{% url 'journals:sign_existing_report' report_id=invitation.related_report.id %}">You can click here to sign this Report</a> (leads to confirmation page).</p> + {% endif %} + {% endif %} + {% else %} + <h3 class="card-title">Referee Invitation</h3> + <p class="card-text"You have declined to contribute a Report. >Nonetheless, we thank you very much for considering this refereeing invitation.</p> + <p class="card-text">Reason: {{ invitation.get_refusal_reason_display }}</p> + {% endif %} + </div> +</div> + +{% comment %} + submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, + related_name='referee_invitations') + referee = models.ForeignKey('scipost.Contributor', related_name='referee_invitations', + blank=True, null=True, on_delete=models.CASCADE) + title = models.CharField(max_length=4, choices=TITLE_CHOICES) + first_name = models.CharField(max_length=30, default='') + last_name = models.CharField(max_length=30, default='') + email_address = models.EmailField() + # if Contributor not found, person is invited to register + invitation_key = models.CharField(max_length=40, default='') + date_invited = models.DateTimeField(default=timezone.now) + invited_by = models.ForeignKey('scipost.Contributor', related_name='referee_invited_by', + blank=True, null=True, on_delete=models.CASCADE) + nr_reminders = models.PositiveSmallIntegerField(default=0) + date_last_reminded = models.DateTimeField(blank=True, null=True) + accepted = models.NullBooleanField(choices=ASSIGNMENT_NULLBOOL, default=None) + date_responded = models.DateTimeField(blank=True, null=True) + refusal_reason = models.CharField(max_length=3, choices=ASSIGNMENT_REFUSAL_REASONS, + blank=True, null=True) + fulfilled = models.BooleanField(default=False) # True if a Report has been submitted + cancelled = models.BooleanField(default=False) # True if EIC has deactivated invitation +{% endcomment %} diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html index a98239cdfab58ee3005ba7820c2c6c8ee2eb8b6d..634cb01892954d79d85ac96e76ac0f58f5886dbd 100644 --- a/submissions/templates/submissions/submission_detail.html +++ b/submissions/templates/submissions/submission_detail.html @@ -22,7 +22,7 @@ {% block content %} <div class="row"> - <div class="col-12"> + <div class="col"> <h2>SciPost Submission Page</h2> <h1 class="text-primary">{{submission.title}}</h1> <h3 class="mb-3">by {{submission.author_list}}</h3> @@ -59,11 +59,6 @@ {% endif %} </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> <h3>Submission summary</h3> {% include 'submissions/_submission_summary.html' with submission=submission hide_title=1 %} @@ -83,6 +78,14 @@ <div class="blockquote">{{ submission.list_of_changes|linebreaks }}</div> {% endif %} </div> + + {% if invitations %} + <div class="col-md-4"> + {% for invitation in invitations %} + {% include 'partials/submissions/refereeing_status_card.html' with invitation=invitation %} + {% endfor %} + </div> + {% endif %} </div> {% if is_author or user|is_in_group:'Editorial College' or user|is_in_group:'Editorial Administrators' %} diff --git a/submissions/views.py b/submissions/views.py index c3d60869ffb5ebbe8484343702f0f9d36839fb62..c1467649878af20fcdb88f031af7096dc7b0e07d 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -211,6 +211,11 @@ def submission_detail(request, arxiv_identifier_w_vn_nr): author_replies = (submission.comments.vetted() .filter(is_author_reply=True).order_by('-date_submitted')) + # User is referee for the Submission + invitations = None + if hasattr(request.user, 'contributor'): + invitations = submission.referee_invitations.filter(referee=request.user.contributor) + recommendations = submission.eicrecommendations.all() context.update({ @@ -224,6 +229,7 @@ def submission_detail(request, arxiv_identifier_w_vn_nr): 'form': form, 'is_author': is_author, 'is_author_unchecked': is_author_unchecked, + 'invitations': invitations, }) return render(request, 'submissions/submission_detail.html', context) @@ -890,8 +896,7 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): RefereeInvitations need to be either accepted or declined by the invited user using this view. The decision will be taken one invitation at a time. """ - invitation = RefereeInvitation.objects.filter( - referee__user=request.user, accepted=None, cancelled=False) + invitation = RefereeInvitation.objects.awaiting_response().filter(referee__user=request.user) if invitation_id: try: invitation = invitation.get(id=invitation_id) @@ -919,7 +924,7 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): invitation.accepted = False decision_string = 'declined' invitation.refusal_reason = form.cleaned_data['refusal_reason'] - messages.success(request, ('<h1>You have declined to contribute a Report</h1>' + messages.success(request, ('<h3>You have declined to contribute a Report</h3>' 'Nonetheless, we thank you very much for considering' ' this refereeing invitation.</p>')) invitation.save() @@ -933,7 +938,10 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): invitation.submission.add_event_for_eic('Referee %s has %s the refereeing invitation.' % (invitation.referee.user.last_name, decision_string)) - return redirect('submissions:accept_or_decline_ref_invitations') + + if request.user.contributor.referee_invitations.awaiting_response().exists(): + return redirect('submissions:accept_or_decline_ref_invitations') + return redirect(invitation.submission.get_absolute_url()) form = ConsiderRefereeInvitationForm() context = { 'invitation': invitation, @@ -1306,7 +1314,7 @@ def submit_report(request, arxiv_identifier_w_vn_nr): % request.user.last_name) messages.success(request, 'Thank you for your Report') - return redirect(reverse('scipost:personal_page')) + return redirect(submission.get_absolute_url()) context = {'submission': submission, 'form': form} return render(request, 'submissions/submit_report.html', context)