diff --git a/comments/models.py b/comments/models.py index e805c5e035ed4b3191d25fa412e23ff08ce43877..b30a7e2c1c01259ef5fab63375e0a10c054a1b9f 100644 --- a/comments/models.py +++ b/comments/models.py @@ -238,12 +238,12 @@ class Comment(models.Model): context['first_name'] = self.author.user.first_name context['last_name'] = self.author.user.last_name if self.submission is not None: - header += ('<a href="/submission/{{ submission_id }}#comment_id{{ id }}">' + header += ('<a href="/submission/{{ arxiv_identifier_w_vn_nr }}#comment_id{{ id }}">' ' \"{{ text_cut }}\"</a><p>submitted on {{ date_submitted }}') - header += (' in submission on <a href="/submission/{{ submission_id }}"' + header += (' in submission on <a href="/submission/{{ arxiv_identifier_w_vn_nr }}"' ' class="pubtitleli">{{ submission_title }}</a> by ' '{{ submission_author_list }}</p>') - context['submission_id'] = self.submission.id + context['arxiv_identifier_w_vn_nr'] = self.submission.arxiv_identifier_w_vn_nr context['submission_title'] = self.submission.title context['submission_author_list'] = self.submission.author_list if self.commentary is not None: @@ -283,11 +283,11 @@ class Comment(models.Model): context['first_name'] = self.author.user.first_name context['last_name'] = self.author.user.last_name if self.submission is not None: - header += ('<a href="/submission/{{ submission_id }}#comment_id{{ id }}"> ' + header += ('<a href="/submission/{{ arxiv_identifier_w_vn_nr }}#comment_id{{ id }}"> ' '\"{{ text_cut }}\"</a>' - ' in submission on <a href="/submission/{{ submission_id }}" class="pubtitleli">' + ' in submission on <a href="/submission/{{ arxiv_identifier_w_vn_nr }}" class="pubtitleli">' '{{ submission_title }}</a> by {{ submission_author_list }}</p>') - context['submission_id'] = self.submission.id + context['arxiv_identifier_w_vn_nr'] = self.submission.arxiv_identifier_w_vn_nr context['submission_title'] = self.submission.title context['submission_author_list'] = self.submission.author_list if self.commentary is not None: diff --git a/comments/templates/comments/vet_submitted_comments.html b/comments/templates/comments/vet_submitted_comments.html index c2315a3ec0a472d2a9ca689474a22d160ed349b6..a9e96013b8dd25c275010343c473c34efd6c03dc 100644 --- a/comments/templates/comments/vet_submitted_comments.html +++ b/comments/templates/comments/vet_submitted_comments.html @@ -22,7 +22,7 @@ {% endif %} {% if comment_to_vet.submission %} - <h3>From Submission (<a href="{% url 'submissions:submission' submission_id=comment_to_vet.submission.id %}">link</a>)</h3> + <h3>From Submission (<a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=comment_to_vet.submission.arxiv_identifier_w_vn_nr %}">link</a>)</h3> {{ comment_to_vet.submission.header_as_table }} <br /> {% endif %} diff --git a/scipost/feeds.py b/scipost/feeds.py index 4680a63bc7c8f18b7013527bcaf520c676a7759d..b1a1b9213820ac4efe52b7e8d48452a9fa62eafc 100644 --- a/scipost/feeds.py +++ b/scipost/feeds.py @@ -23,7 +23,9 @@ class LatestCommentFeed(Feed): if item.commentary: return reverse('commentaries:commentary', kwargs={'arxiv_or_DOI_string': item.commentary.arxiv_or_DOI_string}) elif item.submission: - return reverse('submissions:submission', kwargs={'submission_id': item.submission.id}) + return reverse('submissions:submission', + kwargs={'arxiv_identifier': item.submission.arxiv_identifier, + 'arxiv_vn_nr': item.submission.arxiv_vn_nr}) elif item.thesislink: return reverse('theses:thesis', kwargs={'thesislink_id': item.thesislink.id}) else: diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index 1c5e63d049540bf456db8c762dee7313bac95dc5..23d04493a2151153c433c93d4f63bc5e034c59dc 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -252,8 +252,8 @@ <ul> {% for task in pending_ref_tasks %} <li>{{ task.submission }}, due {{ task.submission.reporting_deadline }}. - <a href="{% url 'submissions:submit_report' submission_id=task.submission.id %}">Submit your Report</a>. - <a href="{% url 'submissions:communication' submission_id=task.submission.id comtype='RtoE' referee_id=request.user.contributor.id %}">Write to the Editor-in-charge</a>. + <a href="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=task.submission.arxiv_identifier_w_vn_nr %}">Submit your Report</a>. + <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=task.submission.arxiv_identifier_w_vn_nr comtype='RtoE' referee_id=request.user.contributor.id %}">Write to the Editor-in-charge</a>. </li> {% endfor %} </ul> diff --git a/scipost/views.py b/scipost/views.py index a5e3911ad96a7262184a6fb93a4af43cf3ac0303..413597d68696c66c3c6e61f0c43fb303827a0dc4 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -502,7 +502,7 @@ def personal_page(request): # Verify if there exist objects authored by this contributor, # whose authorship hasn't been claimed yet own_submissions = (Submission.objects - .filter(authors__in=[contributor]) + .filter(authors__in=[contributor], is_current=True) .order_by('-submission_date')) own_commentaries = (Commentary.objects .filter(authors__in=[contributor]) diff --git a/submissions/forms.py b/submissions/forms.py index 9b8669dbeaad417d5c2c77abe32837047e62d197..a0916f023cc23ed27be262990ec97a1f27c102bd 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -7,6 +7,16 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Div, Field, Fieldset, HTML, Submit +class SubmissionSearchForm(forms.Form): + author = forms.CharField(max_length=100, required=False, label="Author(s)") + title_keyword = forms.CharField(max_length=100, label="Title", required=False) + abstract_keyword = forms.CharField(max_length=1000, required=False, label="Abstract") + + +############################### +# Submission and resubmission # +############################### + class SubmissionIdentifierForm(forms.Form): identifier = forms.CharField(widget=forms.TextInput( {'label': 'arXiv identifier', @@ -16,17 +26,28 @@ class SubmissionIdentifierForm(forms.Form): class SubmissionForm(forms.ModelForm): class Meta: model = Submission - fields = ['discipline', 'submitted_to_journal', 'submission_type', + fields = ['is_resubmission', + 'discipline', 'submitted_to_journal', 'submission_type', 'domain', 'specialization', - 'title', 'author_list', 'abstract', 'arxiv_link', 'metadata', - 'referees_flagged'] + 'title', 'author_list', 'abstract', + 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_wo_vn_nr', + 'arxiv_vn_nr', 'arxiv_link', 'metadata', + 'author_comments', 'list_of_changes', 'referees_flagged'] def __init__(self, *args, **kwargs): super(SubmissionForm, self).__init__(*args, **kwargs) + self.fields['is_resubmission'].widget = forms.HiddenInput() + self.fields['arxiv_identifier_w_vn_nr'].widget = forms.HiddenInput() + self.fields['arxiv_identifier_wo_vn_nr'].widget = forms.HiddenInput() + self.fields['arxiv_vn_nr'].widget = forms.HiddenInput() self.fields['arxiv_link'].widget.attrs.update( {'placeholder': 'ex.: arxiv.org/abs/1234.56789v1'}) self.fields['metadata'].widget = forms.HiddenInput() self.fields['abstract'].widget.attrs.update({'cols': 100}) + self.fields['author_comments'].widget.attrs.update({ + 'placeholder': 'Your resubmission letter', }) + self.fields['list_of_changes'].widget.attrs.update({ + 'placeholder': 'Give a point-by-point list of changes', }) self.fields['referees_flagged'].widget.attrs.update({ 'placeholder': 'Optional: names of referees whose reports should be treated with caution (+ short reason)', 'rows': 3}) @@ -40,12 +61,6 @@ class SubmissionForm(forms.ModelForm): # ) -class SubmissionSearchForm(forms.Form): - author = forms.CharField(max_length=100, required=False, label="Author(s)") - title_keyword = forms.CharField(max_length=100, label="Title", required=False) - abstract_keyword = forms.CharField(max_length=1000, required=False, label="Abstract") - - ###################### # Editorial workflow # ###################### diff --git a/submissions/models.py b/submissions/models.py index 8ae768741486309ee069c611be8cde657985f2e5..84ee8bb33fc4550bf553037d85f83f064efcfec0 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -19,16 +19,18 @@ from journals.models import journals_submit_dict, journals_domains_dict, journal SUBMISSION_STATUS = ( ('unassigned', 'Unassigned, undergoing pre-screening'), -# ('EICrequested', 'A request to become EIC has been sent to a specialty editor (response pending)'), ('assignment_failed', 'Failed to assign Editor-in-charge; manuscript rejected'), ('EICassigned', 'Editor-in-charge assigned, manuscript under review'), ('review_closed', 'Review period closed, editorial recommendation pending'), -# ('EIC_has_recommended', 'Editor-in-charge has provided recommendation'), + # If revisions required: resubmission creates a new Submission object ('revision_requested', 'Editor-in-charge has requested revision'), + ('resubmitted', 'Has been resubmitted'), + # If acceptance/rejection: ('put_to_EC_voting', 'Undergoing voting at the Editorial College'), ('EC_vote_completed', 'Editorial College voting rounded up'), ('accepted', 'Publication decision taken: accept'), ('rejected', 'Publication decision taken: reject'), + # If withdrawn: ('withdrawn', 'Withdrawn by the Authors'), ) submission_status_dict = dict(SUBMISSION_STATUS) @@ -52,7 +54,10 @@ SUBMISSION_TYPE = ( submission_type_dict = dict(SUBMISSION_TYPE) + class Submission(models.Model): + is_current = models.BooleanField(default=True) + is_resubmission = models.BooleanField(default=False) submitted_by = models.ForeignKey(Contributor) editor_in_charge = models.ForeignKey(Contributor, related_name='EIC', blank=True, null=True) submitted_to_journal = models.CharField(max_length=30, choices=SCIPOST_JOURNALS_SUBMIT, @@ -63,6 +68,8 @@ class Submission(models.Model): domain = models.CharField(max_length=3, choices=SCIPOST_JOURNALS_DOMAINS) specialization = models.CharField(max_length=1, choices=SCIPOST_JOURNALS_SPECIALIZATIONS) status = models.CharField(max_length=30, choices=SUBMISSION_STATUS) # set by Editors + author_comments = models.TextField(blank=True, null=True) + list_of_changes = models.TextField(blank=True, null=True) referees_flagged = models.TextField(blank=True, null=True) open_for_reporting = models.BooleanField(default=False) reporting_deadline = models.DateTimeField(default=timezone.now) @@ -76,6 +83,9 @@ class Submission(models.Model): authors_false_claims = models.ManyToManyField (Contributor, blank=True, related_name='authors_sub_false_claims') abstract = models.TextField() + arxiv_identifier_w_vn_nr = models.CharField(max_length=15, default='0000.00000v0') + arxiv_identifier_wo_vn_nr = models.CharField(max_length=10, default='0000.00000') + arxiv_vn_nr = models.PositiveSmallIntegerField(default=1) arxiv_link = models.URLField(verbose_name='arXiv link (including version nr)') metadata = JSONField(default={}, blank=True, null=True) submission_date = models.DateField(verbose_name='submission date') @@ -87,7 +97,12 @@ class Submission(models.Model): ) def __str__ (self): - return self.title[:30] + ' by ' + self.author_list[:30] + header = self.title[:30] + ' by ' + self.author_list[:30] + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + return header @property def reporting_deadline_has_passed(self): @@ -133,12 +148,20 @@ class Submission(models.Model): # for search lists header = ('<li><div class="flex-container">' '<div class="flex-whitebox0"><p>' - '<a href="/submission/{{ id }}" class="pubtitleli">{{ title }}</a></p>' + '<a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">{{ title }}</a></p>' '<p>by {{ author_list }}</p>' - '<p> (submitted {{ submission_date }} to {{ to_journal }})' + '<p>(version {{ arxiv_vn_nr }})') + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + header += ('</p><p> (submitted {{ submission_date }} to {{ to_journal }})' ' - latest activity: {{ latest_activity }}</p>' '</div></div></li>') - context = Context({'id': self.id, 'title': self.title, 'author_list': self.author_list, + context = Context({'arxiv_identifier_w_vn_nr': self.arxiv_identifier_w_vn_nr, + 'arxiv_vn_nr': self.arxiv_vn_nr, + 'title': self.title, 'author_list': self.author_list, 'submission_date': self.submission_date, 'to_journal': journals_submit_dict[self.submitted_to_journal], 'latest_activity': self.latest_activity.strftime('%Y-%m-%d %H:%M')}) @@ -150,12 +173,20 @@ class Submission(models.Model): # includes status specification header = ('<li><div class="flex-container">' '<div class="flex-whitebox0">' - '<p><a href="/submission/{{ id }}" class="pubtitleli">{{ title }}</a></p>' + '<p><a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">{{ title }}</a></p>' '<p>by {{ author_list }}</p>' - '<p> (submitted {{ submission_date }} to {{ to_journal }})' + '<p>(version {{ arxiv_vn_nr }})') + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + header += ('</p><p> (submitted {{ submission_date }} to {{ to_journal }})' ' - latest activity: {{ latest_activity }}</p>' '<p>Status: {{ status }}</p></div></div></li>') - context = Context({'id': self.id, 'title': self.title, 'author_list': self.author_list, + context = Context({'arxiv_identifier_w_vn_nr': self.arxiv_identifier_w_vn_nr, + 'arxiv_vn_nr': self.arxiv_vn_nr, + 'title': self.title, 'author_list': self.author_list, 'submission_date': self.submission_date, 'to_journal': journals_submit_dict[self.submitted_to_journal], 'latest_activity': self.latest_activity.strftime('%Y-%m-%d %H:%M'), @@ -190,19 +221,27 @@ class Submission(models.Model): # for submissions pool header = ('<li><div class="flex-container">' '<div class="flex-whitebox0">' - '<p><a href="/submission/{{ id }}" class="pubtitleli">{{ title }}</a></p>' + '<p><a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">{{ title }}</a></p>' '<p>by {{ author_list }}</p>' - '<p> (submitted {{ submission_date }} to {{ to_journal }})' + '<p>(version {{ arxiv_vn_nr }})') + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + header += ('</p><p> (submitted {{ submission_date }} to {{ to_journal }})' ' - latest activity: {{ latest_activity }}</p>') if self.status == 'unassigned': header += ('<p style="color: red">Status: {{ status }}.' ' You can volunteer to become Editor-in-charge by ' - '<a href="/submissions/volunteer_as_EIC/{{ id }}">clicking here</a>.</p>') + '<a href="/submissions/volunteer_as_EIC/{{ arxiv_identifier_w_vn_nr }}">clicking here</a>.</p>') else: header += '<p>Editor-in-charge: {{ EIC }}</p><p>Status: {{ status }}</p>' header += self.refereeing_status_as_p() header += '</div></div></li>' - context = Context({'id': self.id, 'title': self.title, 'author_list': self.author_list, + context = Context({'arxiv_identifier_w_vn_nr': self.arxiv_identifier_w_vn_nr, + 'arxiv_vn_nr': self.arxiv_vn_nr, + 'title': self.title, 'author_list': self.author_list, 'submission_date': self.submission_date, 'to_journal': journals_submit_dict[self.submitted_to_journal], 'latest_activity': self.latest_activity.strftime('%Y-%m-%d %H:%M'), @@ -216,9 +255,35 @@ class Submission(models.Model): # for Lists header = ('<li><div class="flex-container">' '<div class="flex-whitebox0"><p>' - '<a href="/submission/{{ id }}" class="pubtitleli">{{ title }}</a></p>' - '<p>by {{ author_list }}</p></div></div></li>') - context = Context({'id': self.id, 'title': self.title, 'author_list': self.author_list}) + '<a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">{{ title }}</a></p>' + '<p>by {{ author_list }}</p>' + '<p>(version {{ arxiv_vn_nr }})') + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + header += '</p></div></div></li>' + context = Context({'arxiv_identifier_w_vn_nr': self.arxiv_identifier_w_vn_nr, + 'arxiv_vn_nr': self.arxiv_vn_nr, + 'title': self.title, 'author_list': self.author_list}) + template = Template(header) + return template.render(context) + + + def version_info_as_li (self): + # for listing all versions of a Submission + header = ('<li>' + '<div class="flex-whitebox0"><p>' + '<a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">version {{ arxiv_vn_nr }}</a>') + if self.is_current: + header += ' (current version)' + else: + header += ' (deprecated version)' + header += '</p></div></li>' + context = Context({'arxiv_identifier_w_vn_nr': self.arxiv_identifier_w_vn_nr, + 'arxiv_vn_nr': self.arxiv_vn_nr,}) template = Template(header) return template.render(context) @@ -231,6 +296,7 @@ class Submission(models.Model): return mark_safe(header) + ###################### # Editorial workflow # ###################### @@ -296,14 +362,16 @@ class EditorialAssignment(models.Model): def header_as_li(self): header = ('<li><div class="flex-container">' '<div class="flex-whitebox0">' - '<p><a href="/submission/{{ id }}" class="pubtitleli">{{ title }}</a></p>' + '<p><a href="/submission/{{ arxiv_identifier_w_vn_nr }}" ' + 'class="pubtitleli">{{ title }}</a></p>' '<p>by {{ author_list }}</p>' '<p> (submitted {{ date }} to {{ to_journal }})</p>' '<p>Status: {{ status }}</p><p>Manage this Submission from its ' - '<a href="/submissions/editorial_page/{{ id }}">Editorial Page</a>.' + '<a href="/submissions/editorial_page/{{ arxiv_identifier_w_vn_nr }}">Editorial Page</a>.' '</p></div></div></li>') template = Template(header) - context = Context({'id': self.submission.id, 'title': self.submission.title, + context = Context({'arxiv_identifier_w_vn_nr': self.submission.arxiv_identifier_w_vn_nr, + 'title': self.submission.title, 'author_list': self.submission.author_list, 'date': self.submission.submission_date, 'to_journal': journals_submit_dict[self.submission.submitted_to_journal], diff --git a/submissions/templates/submissions/accept_or_decline_assignment_ack.html b/submissions/templates/submissions/accept_or_decline_assignment_ack.html index e298df409caa53c0b1635a4c4cdd73dfb49ca914..05b4343cef5c5be3e82b691fa2ff917811324e50 100644 --- a/submissions/templates/submissions/accept_or_decline_assignment_ack.html +++ b/submissions/templates/submissions/accept_or_decline_assignment_ack.html @@ -11,7 +11,7 @@ {% elif assignment.accepted %} <h1>Thank you for becoming Editor-in-charge of this submission.</h1> - <p>Please go to the <a href="{% url 'submissions:editorial_page' submission_id=assignment.submission.id %}">Submission's editorial page</a> and select referees now.</p> + <p>Please go to the <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=assignment.submission.arxiv_identifier_w_vn_nr %}">Submission's editorial page</a> and select referees now.</p> {% else %} <h1>Thank you for considering.</h1> <p>Return to the <a href="{% url 'submissions:pool' %}">Submissions Pool</a>.</p> diff --git a/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html b/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html index e25c3d9d3841478938298d098ede4df99ef6403b..d56b1216c9e950ce47ae6c410e004df08e659693 100644 --- a/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html +++ b/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html @@ -7,7 +7,7 @@ <section> {% if invitation.accepted == True %} <h1>Thank you for agree to referee this Submission.</h1> - <p>When you are ready, please go to the <a href="{% url 'submissions:submission' submission_id=invitation.submission.id %}">Submission's page</a> to submit your Report.</p> + <p>When you are ready, please go to the <a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=invitation.submission.arxiv_identifier_w_vn_nr %}">Submission's page</a> to submit your Report.</p> {% else %} <h1>You have declined to contribute a Report.</h1> <p>Nonetheless, we thank you very much for considering this refereeing invitation.</p> diff --git a/submissions/templates/submissions/assign_submission.html b/submissions/templates/submissions/assign_submission.html index 12601f2f8801e8543c90c260740347c94cee958a..682d534c172446339a588ded0848ef7e3629762f 100644 --- a/submissions/templates/submissions/assign_submission.html +++ b/submissions/templates/submissions/assign_submission.html @@ -38,7 +38,7 @@ {% endif %} <h1>Send a new assignment request:</h1> - <form action="{% url 'submissions:assign_submission_ack' submission_id=submission_to_assign.id %}" method="post"> + <form action="{% url 'submissions:assign_submission_ack' arxiv_identifier_w_vn_nr=submission_to_assign.arxiv_identifier_w_vn_nr %}" method="post"> {% csrf_token %} {{ form.as_ul }} <input type="submit" value="Submit" /> diff --git a/submissions/templates/submissions/communication.html b/submissions/templates/submissions/communication.html index a19ffb7ca074faffad4bf9af7d8235492f727353..60ef4953b439375f877fa8503436fbfbf02e028b 100644 --- a/submissions/templates/submissions/communication.html +++ b/submissions/templates/submissions/communication.html @@ -30,13 +30,13 @@ <br/> {% if referee_id %} - <form action="{% url 'submissions:communication' submission_id=submission.id comtype=comtype referee_id=referee_id %}" method="post"> + <form action="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype=comtype referee_id=referee_id %}" method="post"> {% csrf_token %} {{ form }} <input type="submit" value="Send communication"/> </form> {% else %} - <form action="{% url 'submissions:communication' submission_id=submission.id comtype=comtype %}" method="post"> + <form action="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype=comtype %}" method="post"> {% csrf_token %} {{ form }} <input type="submit" value="Send communication"/> diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html index 5b6cf26332eacfa37da2b132349d61e785304d9a..1d9b1e36cfd5d9e5ef151c3bb3fbc2e0a82cc275 100644 --- a/submissions/templates/submissions/editorial_page.html +++ b/submissions/templates/submissions/editorial_page.html @@ -14,10 +14,23 @@ <section> <div class="flex-greybox"> <h1>Editorial Page for Submission</h1> - <h3>(go to the <a href="{% url 'submissions:submission' submission_id=submission.id %}"> + {% if not submission.is_current %} + <h3 style="color: red;">This is not the editorial page for the current version.</h3> + <p>Please go to the current version's page.</p> + {% endif %} + <h3>(go to the <a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}"> Submissions Page</a> to view Reports and Comments)</h3> </div> + {% if other_versions %} + <h3>Other versions of this Submission exist:</h3> + <ul> + {% for vn in other_versions %} + {{ vn.version_info_as_li }} + {% endfor %} + </ul> + {% endif %} + <hr class="hr12"> <div class="row"> <div class="col-4"> @@ -53,14 +66,14 @@ {% if not invitation.accepted == False %} <td> {% if invitation.referee %} - <a href="{% url 'submissions:communication' submission_id=submission.id comtype='EtoR' referee_id=invitation.referee.id %}">Write a communication</a> + <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='EtoR' referee_id=invitation.referee.id %}">Write a communication</a> {% else %} (not yet registered) {% endif %} </td> <td> {% if not invitation.fulfilled %} - <a href="{% url 'submissions:ref_invitation_reminder' submission_id=submission.id invitation_id=invitation.id %}">Send reminder email</a> + <a href="{% url 'submissions:ref_invitation_reminder' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr invitation_id=invitation.id %}">Send reminder email</a> {% else %} <strong style="color: green">Report has been delivered</strong> {% endif %} @@ -84,26 +97,32 @@ <hr class="hr6"/> <h3>Actions:</h3> + {% if not submission.is_current %} + <h3 style="color: red;">BEWARE: This is not the editorial page for the current version.</h3> + <p>The tools here are thus available only for exceptional circumstances (e.g. vetting a late report on a deprecated version).</p> + <p>Please go to the current version's page using the link at the top.</p> + <br/> + {% endif %} <ul> - <li><a href="{% url 'submissions:select_referee' submission_id=submission.id %}"> + <li><a href="{% url 'submissions:select_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}"> Select an additional referee</a> (bear in mind flagged referees if any)</li> <li>Extend the refereeing deadline (currently {{ submission.reporting_deadline }}) by - <a href="{% url 'submissions:extend_refereeing_deadline' submission_id=submission.id days=2 %}">2 days</a>, - <a href="{% url 'submissions:extend_refereeing_deadline' submission_id=submission.id days=7 %}">1 week</a> or - <a href="{% url 'submissions:extend_refereeing_deadline' submission_id=submission.id days=14 %}">2 weeks</a> + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=2 %}">2 days</a>, + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=7 %}">1 week</a> or + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=14 %}">2 weeks</a> {% if submission.reporting_deadline_has_passed %} <b style="color: red">THE REPORTING DEADLINE HAS PASSED</b> {% endif %} </li> <li><a href="{% url 'submissions:vet_submitted_reports' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> {% if not submission.reporting_deadline_has_passed %} - <li><a href="{% url 'submissions:close_refereeing_round' submission_id=submission.id %}">Close the refereeing round</a> (deactivates submission of new Reports and Comments)</li> + <li><a href="{% url 'submissions:close_refereeing_round' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Close the refereeing round</a> (deactivates submission of new Reports and Comments)</li> {% endif %} - <li><a href="{% url 'submissions:communication' submission_id=submission.id comtype='EtoA' %}">Draft and send a communication with the submitting Author</a></li> + <li><a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='EtoA' %}">Draft and send a communication with the submitting Author</a></li> <li>Communicate with a Referee: see the table above. </li> - <li><a href="{% url 'submissions:communication' submission_id=submission.id comtype='EtoS' %}">Draft and send a communication with SciPost Editorial Administration</a></li> - <li><a href="{% url 'submissions:eic_recommendation' submission_id=submission.id %}">Formulate an Editorial Recommendation</a> + <li><a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='EtoS' %}">Draft and send a communication with SciPost Editorial Administration</a></li> + <li><a href="{% url 'submissions:eic_recommendation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Formulate an Editorial Recommendation</a> <p>If you recommend revisions, this will be communicated directly to the Authors, who will be asked to resubmit. <br/>If you recommend acceptance or rejection, this will be put to the Editorial College for ratification.</p> </li> diff --git a/submissions/templates/submissions/eic_recommendation.html b/submissions/templates/submissions/eic_recommendation.html index 75865cbca32d0622675859bd9df9f8fe03f7a32c..135a636cc4ebbf643a53fad4fa01767bec0bb9d8 100644 --- a/submissions/templates/submissions/eic_recommendation.html +++ b/submissions/templates/submissions/eic_recommendation.html @@ -39,9 +39,9 @@ <section> <div class="flex-greybox"> <h1>Formulate Editorial Recommendation for Submission</h1> - <h3>(go to the <a href="{% url 'submissions:submission' submission_id=submission.id %}"> + <h3>(go to the <a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}"> Submissions Page</a> to view Reports and Comments)</h3> - <h3>(go back to the <a href="{% url 'submissions:editorial_page' submission_id=submission.id %}"> + <h3>(go back to the <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}"> Editorial Page</a> to take editorial actions)</h3> </div> @@ -67,7 +67,7 @@ <li>request for revision: sent directly to the authors</li> </div> - <form action="{% url 'submissions:eic_recommendation' submission_id=submission.id %}" method="post"> + <form action="{% url 'submissions:eic_recommendation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> {% csrf_token %} <table> <ul> diff --git a/submissions/templates/submissions/pool.html b/submissions/templates/submissions/pool.html index 31404f8e30ddf30af6f7c9dc9208b28754335d67..7ae17986b6e76cb4ec895330ad9f1f15e40cb6ca 100644 --- a/submissions/templates/submissions/pool.html +++ b/submissions/templates/submissions/pool.html @@ -70,12 +70,12 @@ $(document).ready(function(){ <ul> {% for sub in submissions_in_pool %} - {% if request.user|is_not_author_of_submission:sub.id %} + {% if request.user|is_not_author_of_submission:sub.arxiv_identifier_w_vn_nr %} <br/> {{ sub.header_as_li_for_Fellows }} {% get_obj_perms request.user for sub as "sub_perms" %} {% if "can_take_editorial_actions" in sub_perms or request.user|is_in_group:'Editorial Administrators' %} - <h4><a href="{% url 'submissions:editorial_page' submission_id=sub.id %}"> + <h4><a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=sub.arxiv_identifier_w_vn_nr %}"> Go to this Submission's Editorial Page</a></h4> {% endif %} {% if perms.scipost.can_assign_submissions %} @@ -90,13 +90,13 @@ $(document).ready(function(){ {% if sub.editor_in_charge == None %} <h4>Actions:</h4> <ul> - <li><a href="{% url 'submissions:assign_submission' submission_id=sub.id %}">Send a new assignment request</a></li> - <li><a href="{% url 'submissions:assignment_failed' submission_id=sub.id %}">Close pre-screening: failure to find EIC</a></li> + <li><a href="{% url 'submissions:assign_submission' arxiv_identifier_w_vn_nr=sub.arxiv_identifier_w_vn_nr %}">Send a new assignment request</a></li> + <li><a href="{% url 'submissions:assignment_failed' arxiv_identifier_w_vn_nr=sub.arxiv_identifier_w_vn_nr %}">Close pre-screening: failure to find EIC</a></li> </ul> {% endif %} {% endif %} {% if request.user|is_in_group:'Editorial Administrators' %} - <h4><a href="{% url 'submissions:communication' submission_id=sub.id comtype='StoE' %}">Send a communication to the Editor-in-charge</a></h4> + <h4><a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=sub.arxiv_identifier_w_vn_nr comtype='StoE' %}">Send a communication to the Editor-in-charge</a></h4> {% endif %} {% endif %} {% endfor %} diff --git a/submissions/templates/submissions/select_referee.html b/submissions/templates/submissions/select_referee.html index 40f660bdb5843c8f3421195c758a30b9641f85f3..11affbd0c35fc7c0097c3f316a29cef0c8e5a3ec 100644 --- a/submissions/templates/submissions/select_referee.html +++ b/submissions/templates/submissions/select_referee.html @@ -14,8 +14,8 @@ <section> <div class="flex-greybox"> <h1>Referee Selection Page for Submission</h1> - <h3>(go to the <a href="{% url 'submissions:submission' submission_id=submission.id %}">Submissions Page</a> to view Reports and Comments)</h3> - <h3>(go back to the <a href="{% url 'submissions:editorial_page' submission_id=submission.id %}">Editorial Page</a> to take editorial actions)</h3> + <h3>(go to the <a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Submissions Page</a> to view Reports and Comments)</h3> + <h3>(go back to the <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a> to take editorial actions)</h3> </div> <hr class="hr12"> @@ -37,7 +37,7 @@ <div class="flex-greybox"> <h1>Select an additional Referee</h1> </div> - <form action="{% url 'submissions:select_referee' submission_id=submission.id %}" method="post" id="refereeSearch"> + <form action="{% url 'submissions:select_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post" id="refereeSearch"> {% csrf_token %} {{ ref_search_form }} <input type="submit" value="Find referee"> @@ -68,14 +68,14 @@ <table> {% for contributor in contributors_found %} <tr><td>{{ contributor.user.first_name }} {{ contributor.user.last_name }}</td><td> </td> - <td><a href="{% url 'submissions:send_refereeing_invitation' submission_id=submission.id contributor_id=contributor.id %}">Send refereeing invitation</a></td></tr> + <td><a href="{% url 'submissions:send_refereeing_invitation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr contributor_id=contributor.id %}">Send refereeing invitation</a></td></tr> {% endfor %} </table> {% elif ref_search_form.has_changed %} <p>No Contributor with this last name could be identified.</p> <br/> <p>You can send a registration and refereeing invitation by filling this form:</p> - <form action="{% url 'submissions:recruit_referee' submission_id=submission.id %}" method="post"> + <form action="{% url 'submissions:recruit_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> {% csrf_token %} {% load crispy_forms_tags %} {% crispy ref_recruit_form %} diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html index b902842e7c643c1358d51defb64a0f963f815f09..ab8807dc70ca7b881e0d202a0a8d73c960c51c75 100644 --- a/submissions/templates/submissions/submission_detail.html +++ b/submissions/templates/submissions/submission_detail.html @@ -28,11 +28,23 @@ <section> <div class="flex-greybox"> <h1>SciPost Submission Page</h1> + {% if not submission.is_current %} + <h3 style="color: red;">This is not the current version.</h3> + {% endif %} {% if user.contributor == submission.editor_in_charge %} - <h3>(You are the Editor-in-charge, go to the <a href="{% url 'submissions:editorial_page' submission_id=submission.id %}">Editorial Page</a> to take editorial actions)</h3> + <h3>(You are the Editor-in-charge, go to the <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a> to take editorial actions)</h3> {% endif %} </div> + {% if other_versions %} + <h3>Other versions of this Submission exist:</h3> + <ul> + {% for vn in other_versions %} + {{ vn.version_info_as_li }} + {% endfor %} + </ul> + {% endif %} + <hr class="hr12"> <div class="row"> <div class="col-4"> @@ -43,8 +55,10 @@ <h3>Abstract:</h3> <p>{{ submission.abstract }}</p> -</section> + <h1>Status:</h1> + {{ submission.status_info_as_table }} +</section> {% if user.is_authenticated and user|is_in_group:'Registered Contributors' %} <section> @@ -54,7 +68,7 @@ <ul> {% if submission.open_for_reporting %} {% if perms.scipost.can_referee and not is_author and not is_author_unchecked %} - <li><h3><a href="{% url 'submissions:submit_report' submission.id %}">Contribute a Report</a></h3> + <li><h3><a href="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Contribute a Report</a></h3> <div class="reportingDeadline">Deadline for reporting: {{ submission.reporting_deadline }}</div></li> {% elif is_author_unchecked %} <li><h3>Contribute a Report [deactivated]: the system flagged you as a potential author of this Submission. @@ -235,7 +249,7 @@ <div class="flex-greybox"> <h1>Contribute a Comment:</h1> </div> - <form action="{% url 'submissions:submission' submission.id %}" method="post"> + <form action="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> {% csrf_token %} {% load crispy_forms_tags %} {% crispy form %} diff --git a/submissions/templates/submissions/submit_manuscript.html b/submissions/templates/submissions/submit_manuscript.html index 12fbda3b30669988f773cbba405c7e81f4860b87..91cf08f1658c82ab73f4beaf6f97bdaa493890ce 100644 --- a/submissions/templates/submissions/submit_manuscript.html +++ b/submissions/templates/submissions/submit_manuscript.html @@ -20,6 +20,17 @@ $(document).ready(function(){ } }); + var isresub = $("#id_is_resubmission").val(); + switch(isresub){ + case "True": + $("#id_author_comments").closest('tr').show() + $("#id_list_of_changes").closest('tr').show() + break; + default: + $("#id_author_comments").closest('tr').hide() + $("#id_list_of_changes").closest('tr').hide() + } + }); </script> @@ -46,7 +57,7 @@ $(document).ready(function(){ {% if perms.scipost.can_submit_manuscript %} <div class="flex-greybox"> - <h3><em>You can prefill part of the form using the arXiv identifier:</em></h3> + <h3><em>Please provide the arXiv identifier for your Submission:</em></h3> <p> <em>(give the identifier without prefix but with version number, as per the placeholder)</em> </p> @@ -60,7 +71,12 @@ $(document).ready(function(){ {% if errormessage %} <h3 style="color: red;">Error: {{ errormessage }}</h3> {% endif %} - + + {% if resubmessage %} + <h3 style="color: green;">{{ resubmessage }}</h3> + {% endif %} + + {% if form.arxiv_link.value %} <form id="full_submission_form" action="{% url 'submissions:submit_manuscript' %}" method="post"> {% csrf_token %} <table> @@ -77,6 +93,8 @@ $(document).ready(function(){ author obligations</a>.</p> <input type="submit" value="Submit"/> </form> + {% endif %} + {% else %} <h3>You are currently not allowed to submit a manuscript.</h3> {% endif %} diff --git a/submissions/templates/submissions/submit_report.html b/submissions/templates/submissions/submit_report.html index 814405750a2b2075fa52acba8624e506f95f8c76..f4871650e0570dabca7b05eaa99f2aa9d87fef33 100644 --- a/submissions/templates/submissions/submit_report.html +++ b/submissions/templates/submissions/submit_report.html @@ -26,7 +26,7 @@ <div class="flex-greybox"> <h1>Your report:</h1> </div> - <form action="{% url 'submissions:submit_report' submission.id %}" method="post"> + <form action="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> {% csrf_token %} <table> <ul> diff --git a/submissions/templates/submissions/vet_submitted_report_ack.html b/submissions/templates/submissions/vet_submitted_report_ack.html index b8531e6e13ae062057122253bbf238dedcc35dbd..9fcdf517c50c63f48c5ec5f704a0a235f003ae6d 100644 --- a/submissions/templates/submissions/vet_submitted_report_ack.html +++ b/submissions/templates/submissions/vet_submitted_report_ack.html @@ -6,7 +6,7 @@ <section> <h1>SciPost submitted Report vetted.</h1> - <p><a href="{% url 'submissions:editorial_page' submission_id=submission.id %}">Back to the Submission's Editorial Page</a></p> + <p><a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Back to the Submission's Editorial Page</a></p> </section> {% endblock bodysup %} diff --git a/submissions/templatetags/submissions_extras.py b/submissions/templatetags/submissions_extras.py index eade80ccd88596d89a88d1d7204c3df7bc239f8a..203f651048e927292133e97119f1fe28efd24df0 100644 --- a/submissions/templatetags/submissions_extras.py +++ b/submissions/templatetags/submissions_extras.py @@ -5,8 +5,8 @@ from submissions.models import Submission register = template.Library() @register.filter(name='is_not_author_of_submission') -def is_not_author_of_submission(user, submission_id): - submission = Submission.objects.get(pk=submission_id) +def is_not_author_of_submission(user, arxiv_identifier_w_vn_nr): + submission = Submission.objects.get(arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) return (user.contributor not in submission.authors.all() and (user.last_name not in submission.author_list diff --git a/submissions/urls.py b/submissions/urls.py index 625554901d69e0f97efef1984ce9bd4caa3a7f03..1ce9f4be98e5a9abc5679420b0017ab1d816a01b 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -7,36 +7,63 @@ urlpatterns = [ # Submissions url(r'^$', views.submissions, name='submissions'), url(r'^browse/(?P<discipline>[a-z]+)/(?P<nrweeksback>[0-9]+)/$', views.browse, name='browse'), - url(r'^sub_and_ref_procedure$', TemplateView.as_view(template_name='submissions/sub_and_ref_procedure.html'), name='sub_and_ref_procedure'), - url(r'^author_guidelines$', TemplateView.as_view(template_name='submissions/author_guidelines.html'), name='author_guidelines'), - url(r'^(?P<submission_id>[0-9]+)/$', views.submission_detail, name='submission'), - url(r'^prefill_using_identifier$', views.prefill_using_identifier, name='prefill_using_identifier'), + url(r'^sub_and_ref_procedure$', + TemplateView.as_view(template_name='submissions/sub_and_ref_procedure.html'), name='sub_and_ref_procedure'), + url(r'^author_guidelines$', + TemplateView.as_view(template_name='submissions/author_guidelines.html'), name='author_guidelines'), + url(r'^(?P<arxiv_identifier_wo_vn_nr>[0-9]{4,}.[0-9]{5,})/$', views.submission_detail_wo_vn_nr, + name='submission_wo_vn_nr'), + url(r'^(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/$', + views.submission_detail, name='submission'), + url(r'^prefill_using_identifier$', + views.prefill_using_identifier, name='prefill_using_identifier'), url(r'^submit_manuscript$', views.submit_manuscript, name='submit_manuscript'), url(r'^submit_manuscript_ack$', TemplateView.as_view(template_name='submissions/submit_manuscript_ack.html'), name='submit_manuscript_ack'), url(r'^pool$', views.pool, name='pool'), # Assignment of Editor-in-charge - url(r'^assign_submission/(?P<submission_id>[0-9]+)$', views.assign_submission, name='assign_submission'), - url(r'^assign_submission_ack/(?P<submission_id>[0-9]+)$', views.assign_submission_ack, name='assign_submission_ack'), - url(r'^accept_or_decline_assignment_ack/(?P<assignment_id>[0-9]+)$', views.accept_or_decline_assignment_ack, name='accept_or_decline_assignment_ack'), - url(r'^volunteer_as_EIC/(?P<submission_id>[0-9]+)$', views.volunteer_as_EIC, name='volunteer_as_EIC'), - url(r'^assignment_failed/(?P<submission_id>[0-9]+)$', views.assignment_failed, name='assignment_failed'), + url(r'^assign_submission/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.assign_submission, name='assign_submission'), + url(r'^assign_submission_ack/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.assign_submission_ack, name='assign_submission_ack'), + url(r'^accept_or_decline_assignment_ack/(?P<assignment_id>[0-9]+)$', + views.accept_or_decline_assignment_ack, name='accept_or_decline_assignment_ack'), + url(r'^volunteer_as_EIC/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.volunteer_as_EIC, name='volunteer_as_EIC'), + url(r'^assignment_failed/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.assignment_failed, name='assignment_failed'), # Editorial workflow and refereeing url(r'^editorial_workflow$', views.editorial_workflow, name='editorial_workflow'), - url(r'^editorial_page/(?P<submission_id>[0-9]+)$', views.editorial_page, name='editorial_page'), - url(r'^select_referee/(?P<submission_id>[0-9]+)$', views.select_referee, name='select_referee'), - url(r'^recruit_referee/(?P<submission_id>[0-9]+)$', views.recruit_referee, name='recruit_referee'), - url(r'^send_refereeing_invitation/(?P<submission_id>[0-9]+)/(?P<contributor_id>[0-9]+)$', views.send_refereeing_invitation, name='send_refereeing_invitation'), - url(r'^accept_or_decline_ref_invitations$', views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), - url(r'^accept_or_decline_ref_invitation/(?P<invitation_id>[0-9]+)$', views.accept_or_decline_ref_invitation_ack, name='accept_or_decline_ref_invitation_ack'), - url(r'^ref_invitation_reminder/(?P<submission_id>[0-9]+)/(?P<invitation_id>[0-9]+)$', views.ref_invitation_reminder, name='ref_invitation_reminder'), - url(r'^extend_refereeing_deadline/(?P<submission_id>[0-9]+)/(?P<days>[0-9]+)$', views.extend_refereeing_deadline, name='extend_refereeing_deadline'), - url(r'^close_refereeing_round/(?P<submission_id>[0-9]+)$', views.close_refereeing_round, name='close_refereeing_round'), - url(r'^communication/(?P<submission_id>[0-9]+)/(?P<comtype>[a-zA-Z]{4,})$', views.communication, name='communication'), - url(r'^communication/(?P<submission_id>[0-9]+)/(?P<comtype>[a-zA-Z]{4,})/(?P<referee_id>[0-9]+)$', views.communication, name='communication'), - url(r'^eic_recommendation/(?P<submission_id>[0-9]+)$', views.eic_recommendation, name='eic_recommendation'), + url(r'^editorial_page/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.editorial_page, name='editorial_page'), + url(r'^select_referee/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.select_referee, name='select_referee'), + url(r'^recruit_referee/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.recruit_referee, name='recruit_referee'), + url(r'^send_refereeing_invitation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<contributor_id>[0-9]+)$', + views.send_refereeing_invitation, name='send_refereeing_invitation'), + url(r'^accept_or_decline_ref_invitations$', + views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), + url(r'^accept_or_decline_ref_invitation/(?P<invitation_id>[0-9]+)$', + views.accept_or_decline_ref_invitation_ack, name='accept_or_decline_ref_invitation_ack'), + url(r'^ref_invitation_reminder/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<invitation_id>[0-9]+)$', views.ref_invitation_reminder, name='ref_invitation_reminder'), + url(r'^extend_refereeing_deadline/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<days>[0-9]+)$', + views.extend_refereeing_deadline, name='extend_refereeing_deadline'), + url(r'^close_refereeing_round/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.close_refereeing_round, name='close_refereeing_round'), + url(r'^communication/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<comtype>[a-zA-Z]{4,})$', + views.communication, name='communication'), + url(r'^communication/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<comtype>[a-zA-Z]{4,})/(?P<referee_id>[0-9]+)$', + views.communication, name='communication'), + url(r'^eic_recommendation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.eic_recommendation, name='eic_recommendation'), # Reports - url(r'^submit_report/(?P<submission_id>[0-9]+)$', views.submit_report, name='submit_report'), - url(r'^submit_report_ack$', TemplateView.as_view(template_name='submissions/submit_report_ack.html'), name='submit_report_ack'), - url(r'^vet_submitted_reports$', views.vet_submitted_reports, name='vet_submitted_reports'), - url(r'^vet_submitted_report_ack/(?P<report_id>[0-9]+)$', views.vet_submitted_report_ack, name='vet_submitted_report_ack'), + url(r'^submit_report/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + views.submit_report, name='submit_report'), + url(r'^submit_report_ack$', + TemplateView.as_view(template_name='submissions/submit_report_ack.html'), name='submit_report_ack'), + url(r'^vet_submitted_reports$', + views.vet_submitted_reports, name='vet_submitted_reports'), + url(r'^vet_submitted_report_ack/(?P<report_id>[0-9]+)$', + views.vet_submitted_report_ack, name='vet_submitted_report_ack'), + # Editorial Administration ] diff --git a/submissions/utils.py b/submissions/utils.py index 19e34ec8b544cb27b14fa2f6a2cdea5774b9b359..203793adb5366d3e64531342ac7253554363f796 100644 --- a/submissions/utils.py +++ b/submissions/utils.py @@ -39,6 +39,46 @@ class SubmissionUtils(object): for atd in assignments_to_deprecate: atd.deprecated = True atd.save() + + + @classmethod + def send_authors_submission_ack_email(cls): + """ Requires loading 'submission' attribute. """ + email_text = ('Dear ' + title_dict[cls.submission.submitted_by.title] + ' ' + + cls.submission.submitted_by.user.last_name + + ', \n\nWe have received your Submission to SciPost,\n\n' + + cls.submission.title + ' by ' + cls.submission.author_list + '.' + + '\n\nWe will update you on the results of the pre-screening process ' + 'within the next 5 working days.' + '\n\nYou can track your Submission at any time ' + 'from your personal page https://scipost.org/personal_page.' + + '\n\nWith many thanks,' + + '\n\nThe SciPost Team.') + emailmessage = EmailMessage( + 'SciPost: Submission received', email_text, + 'SciPost Editorial Admin <submissions@scipost.org>', + [cls.submission.submitted_by.user.email, 'submissions@scipost.org'], + reply_to=['submissions@scipost.org']) + emailmessage.send(fail_silently=False) + + + @classmethod + def send_authors_resubmission_ack_email(cls): + """ Requires loading 'submission' attribute. """ + email_text = ('Dear ' + title_dict[cls.submission.submitted_by.title] + ' ' + + cls.submission.submitted_by.user.last_name + + ', \n\nWe have received your Resubmission to SciPost,\n\n' + + cls.submission.title + ' by ' + cls.submission.author_list + '.' + + '\n\nYou can track your Submission at any time ' + 'from your personal page https://scipost.org/personal_page.' + + '\n\nWith many thanks,' + + '\n\nThe SciPost Team.') + emailmessage = EmailMessage( + 'SciPost: Resubmission received', email_text, + 'SciPost Editorial Admin <submissions@scipost.org>', + [cls.submission.submitted_by.user.email, 'submissions@scipost.org'], + reply_to=['submissions@scipost.org']) + emailmessage.send(fail_silently=False) @classmethod @@ -52,7 +92,7 @@ class SubmissionUtils(object): + cls.assignment.submission.author_list + '.' '\n\nYou can take your editorial actions from the editorial page ' 'https://scipost.org/submission/editorial_page/' - + str(cls.assignment.submission.id) + + cls.assignment.submission.arxiv_identifier_w_vn_nr + ' (also accessible from your personal page ' 'https://scipost.org/personal_page under the Editorial Actions tab). ' 'In particular, you should now invite at least 3 referees; you might want to ' @@ -69,7 +109,39 @@ class SubmissionUtils(object): reply_to=['submissions@scipost.org']) emailmessage.send(fail_silently=False) - + + @classmethod + def send_EIC_reappointment_email(cls): + """ Requires loading 'submission' attribute. """ + email_text = ('Dear ' + title_dict[cls.submission.editor_in_charge.title] + ' ' + + cls.submission.editor_in_charge.user.last_name + + ', \n\nThe authors of the SciPost Submission\n\n' + + cls.submission.title + ' by ' + + cls.submission.author_list + + '\n\nhave resubmitted their manuscript. ' + '\n\nAs Editor-in-charge, you can take your editorial actions ' + 'from the editorial page ' + 'https://scipost.org/submission/editorial_page/' + + cls.submission.arxiv_identifier_w_vn_nr + + ' (also accessible from your personal page ' + 'https://scipost.org/personal_page under the Editorial Actions tab). ' + '\n\nYou can either take an immediate acceptance/rejection decision, ' + 'or run a new refereeing round, in which case you ' + 'should now invite at least 3 referees; you might want to ' + 'make sure you are aware of the ' + 'detailed procedure described in the Editorial College by-laws at ' + 'https://scipost.org/EdCol_by-laws.' + '\n\nMany thanks in advance for your collaboration,' + '\n\nThe SciPost Team.') + emailmessage = EmailMessage( + 'SciPost: resubmission received', email_text, + 'SciPost Editorial Admin <submissions@scipost.org>', + [cls.submission.editor_in_charge.user.email], + ['submissions@scipost.org'], + reply_to=['submissions@scipost.org']) + emailmessage.send(fail_silently=False) + + @classmethod def send_author_prescreening_passed_email(cls): """ Requires loading 'assignment' attribute. """ @@ -79,7 +151,8 @@ class SubmissionUtils(object): + cls.assignment.submission.title + ' by ' + cls.assignment.submission.author_list + '\n\nhas successfully passed the pre-screening stage. ' '\n\nA Submission Page has been activated at ' - 'https://scipost.org/submission/' + str(cls.assignment.submission.id) + 'https://scipost.org/submission/' + + cls.assignment.submission.arxiv_identifier_w_vn_nr + ' and a refereeing round has been started, with deadline ' 'currently set at ' + datetime.datetime.strftime(cls.assignment.submission.reporting_deadline, "%Y-%m-%d") @@ -136,13 +209,15 @@ class SubmissionUtils(object): + cls.invitation.submission.editor_in_charge.user.last_name + ', we would like to invite you to referee:\n\n' + cls.invitation.submission.title + ' by ' + cls.invitation.submission.author_list - + ' (see https://scipost.org/submission/' + str(cls.invitation.submission.id) + ').' + + ' (see https://scipost.org/submission/' + + cls.invitation.submission.arxiv_identifier_w_vn_nr + ').' '\n\nPlease visit https://scipost.org/submissions/accept_or_decline_ref_invitations ' '(login required) as soon as possible (ideally within the next 2 days) ' 'in order to accept or decline this invitation.' '\n\nIf you accept, your report can be submitted by simply ' 'clicking on the "Contribute a Report" link at ' - 'https://scipost.org/submission/' + str(cls.invitation.submission.id) + 'https://scipost.org/submission/' + + cls.invitation.submission.arxiv_identifier_w_vn_nr + ' before the reporting deadline (currently set at ' + datetime.datetime.strftime(cls.invitation.submission.reporting_deadline, "%Y-%m-%d") + '; your report will be automatically recognized as an invited report). ' @@ -189,7 +264,8 @@ class SubmissionUtils(object): 'in order to accept or decline this invitation.') email_text += ('\n\nYour report can be submitted by simply clicking on ' 'the "Contribute a Report" link at ' - 'https://scipost.org/submission/' + str(cls.invitation.submission.id) + 'https://scipost.org/submission/' + + cls.invitation.submission.arxiv_identifier_w_vn_nr + ' before the reporting deadline (currently set at ' + datetime.datetime.strftime(cls.invitation.submission.reporting_deadline, "%Y-%m-%d") + '; your report will be automatically recognized as an invited report). ' @@ -227,7 +303,7 @@ class SubmissionUtils(object): if cls.invitation.accepted == False: email_text += ('\n\nPlease invite another referee from the Submission\'s editorial page ' 'at https://scipost.org/submissions/editorial_page/' - + str(cls.invitation.submission.id) + '.') + + cls.invitation.submission.arxiv_identifier_w_vn_nr + '.') email_text += ('\n\nMany thanks for your collaboration,' '\n\nThe SciPost Team.') @@ -273,7 +349,8 @@ class SubmissionUtils(object): cls.report.submission.title + ' by ' + cls.report.submission.author_list + '.') if cls.report.status == 1: email_text += ('\n\nYour Report has been vetted through and is viewable at ' - 'https://scipost.org/submissions/' + str(cls.report.submission.id) + '.') + 'https://scipost.org/submissions/' + + cls.report.submission.arxiv_identifier_w_vn_nr + '.') else: email_text += ('\n\nYour Report has been reviewed by the Editor-in-charge of the Submission, ' 'who decided not to admit it for online posting, citing the reason: ' @@ -310,7 +387,8 @@ class SubmissionUtils(object): ', \n\nA Report has been posted on your recent Submission to SciPost,\n\n' + cls.report.submission.title + ' by ' + cls.report.submission.author_list + '.' '\n\nYou can view it at the Submission Page ' - 'https://scipost.org/submission/' + str(cls.report.submission.id) + '.' + 'https://scipost.org/submission/' + + cls.report.submission.arxiv_identifier_w_vn_nr + '.' '\n\nWe thank you very much for your contribution.' '\n\nSincerely,' + '\n\nThe SciPost Team.') @@ -331,7 +409,8 @@ class SubmissionUtils(object): ', \n\nA Comment has been posted on your recent Submission to SciPost,\n\n' + cls.submission.title + ' by ' + cls.submission.author_list + '.' '\n\nYou can view it at the Submission Page ' - 'https://scipost.org/submission/' + str(cls.submission.id) + '.' + 'https://scipost.org/submission/' + + cls.submission.arxiv_identifier_w_vn_nr + '.' '\n\nWe thank you very much for your contribution.' '\n\nSincerely,' + '\n\nThe SciPost Team.') @@ -359,8 +438,8 @@ class SubmissionUtils(object): recipient_greeting = ('Dear ' + title_dict[cls.communication.submission.editor_in_charge.title] + ' ' + cls.communication.submission.editor_in_charge.user.last_name) - further_action_page = ('https://scipost.org/submission/editorial_page/' + - str(cls.communication.submission.id)) + further_action_page = ('https://scipost.org/submission/editorial_page/' + + cls.communication.submission.arxiv_identifier_w_vn_nr) if cls.communication.comtype == 'AtoE': bcc_emails.append(cls.communication.submission.submitted_by.user.email) elif cls.communication.comtype == 'RtoE': diff --git a/submissions/views.py b/submissions/views.py index 629d7d1706f9018d714059e8ba41c1fb971cabb5..42e849636afa39335085f493b7483fdfe94bf4a3 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -2,17 +2,19 @@ import datetime import feedparser import re import requests +import sys -from django.utils import timezone -from django.shortcuts import get_object_or_404, render, redirect from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.models import User, Group, Permission from django.core.mail import EmailMessage from django.core.urlresolvers import reverse +from django.db import transaction +from django.db.models import Avg from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render, redirect +from django.utils import timezone from django.views.decorators.csrf import csrf_protect -from django.db.models import Avg from guardian.decorators import permission_required_or_403 from guardian.shortcuts import assign_perm @@ -47,19 +49,38 @@ def prefill_using_identifier(request): errormessage = ('The identifier you entered is improperly formatted ' '(did you forget the version number?)') elif (Submission.objects - .filter(arxiv_link__contains=identifierform.cleaned_data['identifier']) + #.filter(arxiv_link__contains=identifierform.cleaned_data['identifier']) + .filter(arxiv_identifier_w_vn_nr=identifierform.cleaned_data['identifier']) .exists()): - errormessage = 'This preprint has already been submitted to SciPost.' + errormessage = 'This preprint version has already been submitted to SciPost.' if errormessage != '': form = SubmissionForm() return render(request, 'submissions/submit_manuscript.html', {'identifierform': identifierform, 'form': form, 'errormessage': errormessage}) # Otherwise we query arXiv for the information: + identifier_without_vn_nr = identifierform.cleaned_data['identifier'].rpartition('v')[0] + arxiv_vn_nr = int(identifierform.cleaned_data['identifier'].rpartition('v')[2]) + is_resubmission = False + resubmessage = '' + previous_submissions = Submission.objects.filter( + arxiv_identifier_wo_vn_nr=identifier_without_vn_nr).order_by('-arxiv_vn_nr') + if previous_submissions.exists(): + is_resubmission = True + resubmessage = ('There already exists a preprint with this arXiv identifier ' + 'but a different version number. \nYour Submission will be ' + 'handled as a resubmission.') try: queryurl = ('http://export.arxiv.org/api/query?id_list=%s' % identifierform.cleaned_data['identifier']) arxivquery = feedparser.parse(queryurl) + # Flag error if preprint doesn't exist + try: + test = arxivquery['entries'][0]['title'] + except KeyError: + errormessage = 'A preprint associated to this identifier does not exist.' + except: + pass # If paper has been published, should comment on published version try: arxiv_journal_ref = arxivquery['entries'][0]['arxiv_journal_ref'] @@ -79,6 +100,21 @@ def prefill_using_identifier(request): 'errormessage': errormessage} return render(request, 'submissions/submit_manuscript.html', context) # otherwise prefill the form: + # metadata = arxivquery + # title = arxivquery['entries'][0]['title'] + # authorlist = arxivquery['entries'][0]['authors'][0]['name'] + # for author in arxivquery['entries'][0]['authors'][1:]: + # authorlist += ', ' + author['name'] + # arxiv_link = arxivquery['entries'][0]['id'] + # abstract = arxivquery['entries'][0]['summary'] + # form = SubmissionForm( + # initial={'is_resubmission': is_resubmission, + # 'metadata': metadata, + # 'title': title, 'author_list': authorlist, + # 'arxiv_identifier_w_vn_nr': identifierform.cleaned_data['identifier'], + # 'arxiv_identifier_wo_vn_nr': identifier_without_vn_nr, + # 'arxiv_vn_nr': arxiv_vn_nr, + # 'arxiv_link': arxiv_link, 'abstract': abstract}) metadata = arxivquery title = arxivquery['entries'][0]['title'] authorlist = arxivquery['entries'][0]['authors'][0]['name'] @@ -86,15 +122,31 @@ def prefill_using_identifier(request): authorlist += ', ' + author['name'] arxiv_link = arxivquery['entries'][0]['id'] abstract = arxivquery['entries'][0]['summary'] - form = SubmissionForm( - initial={'metadata': metadata, + initialdata={'is_resubmission': is_resubmission, + 'metadata': metadata, 'title': title, 'author_list': authorlist, - 'arxiv_identifier': identifierform.cleaned_data['identifier'], - 'arxiv_link': arxiv_link, 'abstract': abstract}) - context = {'identifierform': identifierform, 'form': form} + 'arxiv_identifier_w_vn_nr': identifierform.cleaned_data['identifier'], + 'arxiv_identifier_wo_vn_nr': identifier_without_vn_nr, + 'arxiv_vn_nr': arxiv_vn_nr, + 'arxiv_link': arxiv_link, 'abstract': abstract} + if is_resubmission: + initialdata['submitted_to_journal'] = previous_submissions[0].submitted_to_journal + initialdata['submission_type'] = previous_submissions[0].submission_type + initialdata['discipline'] = previous_submissions[0].discipline + initialdata['domain'] = previous_submissions[0].domain + initialdata['specialization'] = previous_submissions[0].specialization + initialdata['referees_flagged'] = previous_submissions[0].referees_flagged + form = SubmissionForm(initial=initialdata) + context = {'identifierform': identifierform, + 'form': form, + 'resubmessage': resubmessage} return render(request, 'submissions/submit_manuscript.html', context) except: - pass + print("Unexpected error in prefill_using_identifier:", sys.exc_info()[0]) + context = {'identifierform': identifierform, + 'form': SubmissionForm(), + 'errormessage': errormessage,} + return render(request, 'submissions/submit_manuscript.html', context) else: pass return redirect(reverse('submissions:submit_manuscript')) @@ -102,6 +154,7 @@ def prefill_using_identifier(request): @login_required @permission_required('scipost.can_submit_manuscript', raise_exception=True) +@transaction.atomic def submit_manuscript(request): if request.method == 'POST': form = SubmissionForm(request.POST) @@ -116,8 +169,11 @@ def submit_manuscript(request): {'identifierform': identifierform, 'form': form, 'errormessage': errormessage}) submission = Submission ( + is_current = True, + is_resubmission = form.cleaned_data['is_resubmission'], submitted_by = submitted_by, submitted_to_journal = form.cleaned_data['submitted_to_journal'], + submission_type = form.cleaned_data['submission_type'], discipline = form.cleaned_data['discipline'], domain = form.cleaned_data['domain'], specialization = form.cleaned_data['specialization'], @@ -125,6 +181,9 @@ def submit_manuscript(request): title = form.cleaned_data['title'], author_list = form.cleaned_data['author_list'], abstract = form.cleaned_data['abstract'], + arxiv_identifier_w_vn_nr = form.cleaned_data['arxiv_identifier_w_vn_nr'], + arxiv_identifier_wo_vn_nr = form.cleaned_data['arxiv_identifier_wo_vn_nr'], + arxiv_vn_nr = form.cleaned_data['arxiv_vn_nr'], arxiv_link = form.cleaned_data['arxiv_link'], metadata = form.cleaned_data['metadata'], submission_date = timezone.now(), @@ -133,22 +192,44 @@ def submit_manuscript(request): submission.save() submission.authors.add(submitted_by) # must be author to be able to submit submission.save() - email_text = ('Dear ' + title_dict[submitted_by.title] + ' ' + - submitted_by.user.last_name + - ', \n\nWe have received your Submission to SciPost,\n\n' + - submission.title + ' by ' + submission.author_list + '.' + - '\n\nWe will update you on the results of the pre-screening process ' - 'within the next 5 working days.' - '\n\nYou can track your Submission at any time ' - 'from your personal page https://scipost.org/personal_page.' + - '\n\nWith many thanks,' + - '\n\nThe SciPost Team.') - emailmessage = EmailMessage( - 'SciPost: Submission received', email_text, - 'SciPost Editorial Admin <submissions@scipost.org>', - [submitted_by.user.email, 'submissions@scipost.org'], - reply_to=['submissions@scipost.org']) - emailmessage.send(fail_silently=False) + # If this is a resubmission, mark previous submissions as deprecated: + if form.cleaned_data['is_resubmission']: + previous_submissions = Submission.objects.filter( + arxiv_identifier_wo_vn_nr=form.cleaned_data['arxiv_identifier_wo_vn_nr'] + ).exclude(pk=submission.id).order_by('-arxiv_vn_nr') + for sub in previous_submissions: + sub.is_current = False + sub.open_for_reporting = False + sub.save() + # Handle this submission in same way as if assignment had been accepted + submission.open_for_reporting = True + deadline = timezone.now() + datetime.timedelta(days=28) # for papers + if submission.submitted_to_journal == 'SciPost Physics Lecture Notes': + deadline += datetime.timedelta(days=28) + submission.reporting_deadline = deadline + submission.open_for_commenting = True + submission.latest_activity = timezone.now() + # We keep the same (most recent) Editor-in-charge by default + submission.editor_in_charge = previous_submissions[0].editor_in_charge + submission.status = 'EICassigned' + submission.save() + assignment = EditorialAssignment( + submission=submission, + to=submission.editor_in_charge, + accepted=True, + date_created=timezone.now(), + ) + assignment.save() + SubmissionUtils.load({'submission': submission}) + SubmissionUtils.send_authors_resubmission_ack_email() + assign_perm('can_take_editorial_actions', submission.editor_in_charge.user, submission) + ed_admins = Group.objects.get(name='Editorial Administrators') + assign_perm('can_take_editorial_actions', ed_admins, submission) + SubmissionUtils.send_EIC_reappointment_email() + else: + SubmissionUtils.load({'submission': submission}) + SubmissionUtils.send_authors_submission_ack_email() + return HttpResponseRedirect(reverse('submissions:submit_manuscript_ack')) else: # form is invalid pass @@ -160,6 +241,9 @@ def submit_manuscript(request): def submissions(request): + """ + Main method for viewing Submissions. + """ if request.method == 'POST': form = SubmissionSearchForm(request.POST) if form.is_valid() and form.has_changed(): @@ -178,7 +262,8 @@ def submissions(request): submission_recent_list = Submission.objects.filter( latest_activity__gte=timezone.now() + datetime.timedelta(days=-28) - ).exclude(status__in=['unassigned', 'assignment_failed']).order_by('-submission_date') + ).exclude(status__in=['unassigned', 'assignment_failed'], + is_current=False).order_by('-submission_date') context = {'form': form, 'submission_search_list': submission_search_list, 'submission_recent_list': submission_recent_list } return render(request, 'submissions/submissions.html', context) @@ -203,14 +288,24 @@ def browse(request, discipline, nrweeksback): submission_browse_list = Submission.objects.filter( discipline=discipline, latest_activity__gte=timezone.now() + datetime.timedelta(weeks=-int(nrweeksback)) - ).exclude(status__in=['unassigned', 'assignment_failed']).order_by('-submission_date') + ).exclude(status__in=['unassigned', 'assignment_failed'], + is_current=False).order_by('-submission_date') context = {'form': form, 'discipline': discipline, 'nrweeksback': nrweeksback, 'submission_browse_list': submission_browse_list } return render(request, 'submissions/submissions.html', context) -def submission_detail(request, submission_id): - submission = get_object_or_404(Submission, pk=submission_id) +def submission_detail_wo_vn_nr(request, arxiv_identifier_wo_vn_nr): + submission = get_object_or_404(Submission, arxiv_identifier_wo_vn_nr=arxiv_identifier_wo_vn_nr, + is_current=True) + return(submission_detail(request, submission.arxiv_identifier_w_vn_nr)) + + +def submission_detail(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + other_versions = Submission.objects.filter( + arxiv_identifier_wo_vn_nr=submission.arxiv_identifier_wo_vn_nr + ).exclude(pk=submission.id) comments = submission.comment_set.all() if request.method == 'POST': form = CommentForm(request.POST) @@ -234,7 +329,7 @@ def submission_detail(request, submission_id): newcomment.save() author.nr_comments = Comment.objects.filter(author=author).count() author.save() - request.session['submission_id'] = submission_id + request.session['arxiv_identifier_w_vn_nr'] = submission.arxiv_identifier_w_vn_nr return HttpResponseRedirect(reverse('comments:comment_submission_ack')) else: form = CommentForm() @@ -254,6 +349,7 @@ def submission_detail(request, submission_id): is_author = False is_author_unchecked = False context = {'submission': submission, + 'other_versions': other_versions, 'comments': (comments.filter(status__gte=1, is_author_reply=False) .order_by('-date_submitted')), 'invited_reports': reports.filter(status__gte=1, invited=True), @@ -287,7 +383,7 @@ def pool(request): All members of the Editorial College have access. """ submissions_in_pool=(Submission.objects.all() - .exclude(status__in=['decided']) + .exclude(status__in=['decided'], is_current=False) .order_by('-submission_date')) contributor = Contributor.objects.get(user=request.user) assignments_to_consider = EditorialAssignment.objects.filter( @@ -301,8 +397,9 @@ def pool(request): @login_required @permission_required('scipost.can_assign_submissions', raise_exception=True) -def assign_submission(request, submission_id): - submission_to_assign = get_object_or_404 (Submission, pk=submission_id) +def assign_submission(request, arxiv_identifier_w_vn_nr): + submission_to_assign = get_object_or_404(Submission, + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) #form = AssignSubmissionForm(discipline=submission_to_assign.discipline, specialization=submission_to_assign.specialization) # reactivate later on form = AssignSubmissionForm(discipline=submission_to_assign.discipline) context = {'submission_to_assign': submission_to_assign, @@ -312,8 +409,9 @@ def assign_submission(request, submission_id): @login_required @permission_required('scipost.can_assign_submissions', raise_exception=True) -def assign_submission_ack(request, submission_id): - submission = Submission.objects.get(pk=submission_id) +def assign_submission_ack(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404(Submission, + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) if request.method == 'POST': form = AssignSubmissionForm(request.POST, discipline=submission.discipline) if form.is_valid(): @@ -351,6 +449,7 @@ def assign_submission_ack(request, submission_id): @login_required @permission_required('scipost.can_take_charge_of_submissions', raise_exception=True) +@transaction.atomic def accept_or_decline_assignment_ack(request, assignment_id): contributor = Contributor.objects.get(user=request.user) assignment = get_object_or_404 (EditorialAssignment, pk=assignment_id) @@ -402,12 +501,13 @@ def accept_or_decline_assignment_ack(request, assignment_id): @login_required @permission_required('scipost.can_take_charge_of_submissions', raise_exception=True) -def volunteer_as_EIC(request, submission_id): +@transaction.atomic +def volunteer_as_EIC(request, arxiv_identifier_w_vn_nr): """ Called when a Fellow volunteers while perusing the submissions pool. This is an adapted version of the accept_or_decline_assignment_ack method. """ - submission = get_object_or_404(Submission, pk=submission_id) + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) errormessage = None if submission.status == 'assignment_failed': errormessage = 'This Submission has failed pre-screening and has been rejected.' @@ -440,6 +540,8 @@ def volunteer_as_EIC(request, submission_id): SubmissionUtils.load({'assignment': assignment}) SubmissionUtils.deprecate_other_assignments() assign_perm('can_take_editorial_actions', contributor.user, submission) + ed_admins = Group.objects.get(name='Editorial Administrators') + assign_perm('can_take_editorial_actions', ed_admins, submission) SubmissionUtils.send_EIC_appointment_email() context = {'assignment': assignment} @@ -448,13 +550,14 @@ def volunteer_as_EIC(request, submission_id): @login_required @permission_required('scipost.can_assign_submissions', raise_exception=True) -def assignment_failed(request, submission_id): +@transaction.atomic +def assignment_failed(request, arxiv_identifier_w_vn_nr): """ No Editorial Fellow has accepted or volunteered to become Editor-in-charge. The submission is rejected. This method is called from pool.html by an Editorial Administrator. """ - submission = get_object_or_404(Submission, pk=submission_id) + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) submission.status = 'assignment_failed' submission.latest_activity = timezone.now() submission.save() @@ -467,25 +570,31 @@ def assignment_failed(request, submission_id): @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def editorial_page(request, submission_id): - submission = get_object_or_404(Submission, pk=submission_id) +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def editorial_page(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + other_versions = Submission.objects.filter( + arxiv_identifier_wo_vn_nr=submission.arxiv_identifier_wo_vn_nr + ).exclude(pk=submission.id) ref_invitations = RefereeInvitation.objects.filter(submission=submission) nr_reports_to_vet = (Report.objects .filter(status=0, submission__editor_in_charge=request.user.contributor) .count()) communications = (EditorialCommunication.objects .filter(submission=submission).order_by('timestamp')) - context = {'submission': submission, 'ref_invitations': ref_invitations, + context = {'submission': submission, 'other_versions': other_versions, + 'ref_invitations': ref_invitations, 'nr_reports_to_vet': nr_reports_to_vet, 'communications': communications} return render(request, 'submissions/editorial_page.html', context) @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def select_referee(request, submission_id): - submission = get_object_or_404(Submission, pk=submission_id) +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def select_referee(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) queryresults = '' if request.method == 'POST': ref_search_form = RefereeSelectForm(request.POST) @@ -518,8 +627,10 @@ def select_referee(request, submission_id): @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def recruit_referee(request, submission_id): +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +@transaction.atomic +def recruit_referee(request, arxiv_identifier_w_vn_nr): """ If the Editor-in-charge does not find the desired referee among Contributors (otherwise, the method send_refereeing_invitation below is used instead), @@ -528,7 +639,7 @@ def recruit_referee(request, submission_id): The pending refereeing invitation is then recognized upon registration, using the invitation token. """ - submission = get_object_or_404(Submission, pk=submission_id) + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) if request.method == 'POST': ref_recruit_form = RefereeRecruitmentForm(request.POST) if ref_recruit_form.is_valid(): @@ -567,19 +678,22 @@ def recruit_referee(request, submission_id): ref_invitation.invitation_key = reg_invitation.invitation_key ref_invitation.save() - return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id})) + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def send_refereeing_invitation(request, submission_id, contributor_id): +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +@transaction.atomic +def send_refereeing_invitation(request, arxiv_identifier_w_vn_nr, contributor_id): """ This method is called by the EIC from the submission's editorial_page, in the case where the referee is an identified Contributor. For a referee who isn't a Contributor yet, the method recruit_referee above is called instead. """ - submission = get_object_or_404(Submission, pk=submission_id) + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) contributor = get_object_or_404(Contributor, pk=contributor_id) invitation = RefereeInvitation(submission=submission, referee=contributor, @@ -594,12 +708,14 @@ def send_refereeing_invitation(request, submission_id, contributor_id): invitation.save() SubmissionUtils.load({'invitation': invitation}) SubmissionUtils.send_refereeing_invitation_email() - return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id})) + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def ref_invitation_reminder(request, submission_id, invitation_id): +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def ref_invitation_reminder(request, arxiv_identifier_w_vn_nr, invitation_id): """ This method is used by the Editor-in-charge from the editorial_page when a referee has been invited but hasn't answered yet. @@ -612,7 +728,7 @@ def ref_invitation_reminder(request, submission_id, invitation_id): SubmissionUtils.load({'invitation': invitation}) SubmissionUtils.send_ref_reminder_email() return redirect(reverse('submissions:editorial_page', - kwargs={'submission_id': submission_id})) + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required @@ -648,21 +764,24 @@ def accept_or_decline_ref_invitation_ack(request, invitation_id): @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def extend_refereeing_deadline(request, submission_id, days): - submission = get_object_or_404 (Submission, pk=submission_id) - submission.reporting_deadline = timezone.now() + datetime.timedelta(days=int(days)) +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def extend_refereeing_deadline(request, arxiv_identifier_w_vn_nr, days): + submission = get_object_or_404 (Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + submission.reporting_deadline += datetime.timedelta(days=int(days)) submission.open_for_reporting = True submission.open_for_commenting = True submission.status = 'EICassigned' submission.latest_activity = timezone.now() submission.save() - return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id})) + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def close_refereeing_round(request, submission_id): +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def close_refereeing_round(request, arxiv_identifier_w_vn_nr): """ Called by the Editor-in-charge when a satisfactory number of reports have been gathered. @@ -670,23 +789,24 @@ def close_refereeing_round(request, submission_id): round off any replies to reports or comments before the editorial recommendation is formulated. """ - submission = get_object_or_404 (Submission, pk=submission_id) + submission = get_object_or_404 (Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) submission.open_for_reporting = False submission.open_for_commenting = False submission.status = 'review_closed' submission.reporting_deadline = timezone.now() submission.latest_activity = timezone.now() submission.save() - return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id})) + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required -def communication(request, submission_id, comtype, referee_id=None): +def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): """ Communication between editor-in-charge, author or referee occurring during the submission refereeing. """ - submission = get_object_or_404 (Submission, pk=submission_id) + submission = get_object_or_404 (Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) errormessage = None if not comtype in ed_comm_choices_dict.keys(): errormessage = 'Unknown type of cummunication.' @@ -723,7 +843,7 @@ def communication(request, submission_id, comtype, referee_id=None): SubmissionUtils.send_communication_email() if comtype == 'EtoA' or comtype == 'EtoR' or comtype == 'EtoS': return redirect(reverse('submissions:editorial_page', - kwargs={'submission_id': submission_id})) + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) elif comtype == 'AtoE' or comtype == 'RtoE': return redirect(reverse('scipost:personal_page')) elif comtype == 'StoE': @@ -735,9 +855,11 @@ def communication(request, submission_id, comtype, referee_id=None): @login_required -@permission_required_or_403('can_take_editorial_actions', (Submission, 'id', 'submission_id')) -def eic_recommendation(request, submission_id): - submission = get_object_or_404 (Submission, pk=submission_id) +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +@transaction.atomic +def eic_recommendation(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404 (Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) if request.method == 'POST': form = EICRecommendationForm(request.POST) if form.is_valid(): @@ -764,10 +886,16 @@ def eic_recommendation(request, submission_id): elif (recommendation.recommendation == -1 or recommendation.recommendation == -2): submission.status = 'revision_requested' + submission.open_for_reporting = False submission.save() + # The EIC has fulfilled this editorial assignment. + assignment = get_object_or_404(EditorialAssignment, + submission=submission, to=request.user.contributor) + assignment.completed = True + assignment.save() return redirect(reverse('submissions:editorial_page', - kwargs={'submission_id': submission_id})) + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) else: form = EICRecommendationForm() context = {'submission': submission, 'form': form} @@ -780,8 +908,9 @@ def eic_recommendation(request, submission_id): @login_required @permission_required('scipost.can_referee', raise_exception=True) -def submit_report(request, submission_id): - submission = get_object_or_404 (Submission, pk=submission_id) +@transaction.atomic +def submit_report(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404 (Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) # Check whether the user can submit a report: is_author = request.user.contributor in submission.authors.all() is_author_unchecked = (not is_author @@ -841,7 +970,7 @@ def submit_report(request, submission_id): author.save() SubmissionUtils.load({'report': newreport}) SubmissionUtils.email_EIC_report_delivered() - request.session['submission_id'] = submission_id + request.session['arxiv_identifier_w_vn_nr'] = arxiv_identifier_w_vn_nr return HttpResponseRedirect(reverse('submissions:submit_report_ack')) else: @@ -862,6 +991,7 @@ def vet_submitted_reports(request): @permission_required('scipost.can_take_charge_of_submissions', raise_exception=True) +@transaction.atomic def vet_submitted_report_ack(request, report_id): if request.method == 'POST': form = VetReportForm(request.POST)