diff --git a/colleges/models.py b/colleges/models.py index 8f4f8ac110f51050320e5a738ea5d8c652f4f3bd..312021771eb5501790b86f011e264e206628d2c9 100644 --- a/colleges/models.py +++ b/colleges/models.py @@ -13,13 +13,15 @@ from .managers import FellowQuerySet class Fellowship(TimeStampedModel): - """ - Editorial College Fellowship connecting Editorial College and Contributors, - possibly with a limiting start/until date. + """A Fellowship gives access to the Submission Pool to Contributors. + + Editorial College Fellowship connects the Editorial College and Contributors, + possibly with a limiting start/until date and/or a Proceedings event. The date range will effectively be used while determining 'the pool' for a specific Submission, so it has a direct effect on the submission date. """ + contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE, related_name='fellowships') start_date = models.DateField(null=True, blank=True) @@ -39,15 +41,15 @@ class Fellowship(TimeStampedModel): return _str def get_absolute_url(self): + """Return the admin fellowship page.""" return reverse('colleges:fellowship', args=(self.id,)) def sibling_fellowships(self): - """ - Return all Fellowships that are directly related to the Fellow of this Fellowship. - """ + """Return all Fellowships that are directly related to the Fellow of this Fellowship.""" return self.contributor.fellowships.all() def is_active(self): + """Check if the instance is within start and until date.""" today = datetime.date.today() if not self.start_date: if not self.until_date: diff --git a/colleges/views.py b/colleges/views.py index 14e4765853905caf5136d68b349e40d26eaf769b..babe8a45304bc2f92231d82ffa63a6c7a3f2ecec 100644 --- a/colleges/views.py +++ b/colleges/views.py @@ -19,9 +19,7 @@ from .models import Fellowship @login_required @permission_required('scipost.can_manage_college_composition', raise_exception=True) def fellowships(request): - """ - List all fellowships to be able to edit them, or create new ones. - """ + """List all fellowships to be able to edit them, or create new ones.""" fellowships = Fellowship.objects.active() context = { @@ -33,9 +31,7 @@ def fellowships(request): @login_required @permission_required('scipost.can_manage_college_composition', raise_exception=True) def fellowship_detail(request, id): - """ - View details of a specific fellowship - """ + """View details of a specific fellowship.""" fellowship = get_object_or_404(Fellowship, id=id) context = { diff --git a/invitations/views.py b/invitations/views.py index 36f2e40338e4c885ec5b57dda77a444819b028fa..d54c002300f5b2aa41fa581f72cb5a44303bface 100644 --- a/invitations/views.py +++ b/invitations/views.py @@ -164,7 +164,7 @@ class RegistrationInvitationsUpdateView(RequestArgumentMixin, PermissionsMixin, class RegistrationInvitationsMergeView(RequestArgumentMixin, PermissionsMixin, UpdateView): - permission_required = 'scipost.can_invite_fellows' + permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.no_response() form_class = RegistrationInvitationMergeForm template_name = 'invitations/registrationinvitation_form_merge.html' diff --git a/mails/templates/mail_templates/registration_invitation.html b/mails/templates/mail_templates/registration_invitation.html index fceaa5f9956115a983731e522ee8a74e28fb4f16..beae41fdc428089bb93649de69e6512c273eeac2 100644 --- a/mails/templates/mail_templates/registration_invitation.html +++ b/mails/templates/mail_templates/registration_invitation.html @@ -80,7 +80,7 @@ Dear {% if invitation.message_style == 'F' %}{{ invitation.get_title_display }} </ul> {% endif %} <p> - I would hereby like to use this opportunity to quickly introduce you to the SciPost initiative, and to invite you to become an active Contributor. + We would hereby like to use this opportunity to quickly introduce you to the SciPost initiative, and to invite you to become an active Contributor. </p> <p> In summary, SciPost.org is a publication portal managed by @@ -115,10 +115,12 @@ Dear {% if invitation.message_style == 'F' %}{{ invitation.get_title_display }} <p> Many thanks in advance for taking a few minutes to look into it, <br> - On behalf of the SciPost Foundation, - <br> - <br> - {{ invitation.invited_by.contributor.get_title_display }} {{ invitation.invited_by.first_name }} {{ invitation.invited_by.last_name }} + <br>SciPost Foundation + <br>Institute for Theoretial Physics + <br>University of Amsterdam + <br>Science Park 904 + <br>1098 XH Amsterdam + <br>The Netherlands </p> {% elif invitation.invitation_type == 'F' %} {# Fellow invite #} diff --git a/mails/templates/mail_templates/submissions_assignment_failed.html b/mails/templates/mail_templates/submissions_assignment_failed.html new file mode 100644 index 0000000000000000000000000000000000000000..382b4217405c28280daa788d592d42fab903fd3c --- /dev/null +++ b/mails/templates/mail_templates/submissions_assignment_failed.html @@ -0,0 +1,17 @@ +<p>Dear {{ submission.submitted_by.get_title_display }} {{ submission.submitted_by.user.last_name }},</p> +<p>Your recent Submission to SciPost,</p> +<p>{{ submission.title }}</p> +<p>by {{ submission.author_list }}</p> +<p> + has unfortunately not passed the pre-screening stage. + We therefore regret to inform you that we will not + process your paper further towards publication, and that you + are now free to send your manuscript to an alternative journal. +</p> + + +<p>We nonetheless thank you very much for your contribution.</p> +<p>Sincerely,</p> +<p>The SciPost Team.</p> + +{% include 'email/_footer.html' %} diff --git a/mails/templates/mail_templates/submissions_assignment_failed.json b/mails/templates/mail_templates/submissions_assignment_failed.json new file mode 100644 index 0000000000000000000000000000000000000000..9b1051a0bc9cdfdbf1e524a93326f6e2f45b55fd --- /dev/null +++ b/mails/templates/mail_templates/submissions_assignment_failed.json @@ -0,0 +1,8 @@ +{ + "subject": "SciPost: pre-screening not passed", + "to_address": "submitted_by.user.email", + "bcc_to": "submissions@scipost.org", + "from_address_name": "SciPost Editorial Admin", + "from_address": "submissions@scipost.org", + "context_object": "submission" +} diff --git a/mails/templates/mails/mail_form.html b/mails/templates/mails/mail_form.html index f1afc1a879536a84a3fe69de45cb7930ce025d19..6bae596d97c8f88e000f6f83829e5c554c974e64 100644 --- a/mails/templates/mails/mail_form.html +++ b/mails/templates/mails/mail_form.html @@ -6,7 +6,13 @@ {% block content %} - <h1>Complete and send mail</h1> + {% if header_template %} + {% include header_template with object=object %} + <hr class="divider"> + <h2 class="highlight">Complete and send mail</h2> + {% else %} + <h1 class="highlight">Complete and send mail</h1> + {% endif %} <h3 class="mb-4">You may edit the mail before sending it.</h3> <form enctype="multipart/form-data" method="post"> diff --git a/mails/views.py b/mails/views.py index 6132d392342310e7dff63ef38295450998d5f0f7..36578a74a7baa349e13f3a40723c0ff63ae61cc4 100644 --- a/mails/views.py +++ b/mails/views.py @@ -15,6 +15,7 @@ class MailEditingSubView(object): self.request = request self.context = kwargs.get('context', {}) self.template_name = kwargs.get('template', 'mails/mail_form.html') + self.header_template = kwargs.get('header_template', '') self.mail_form = EmailTemplateForm(request.POST or None, mail_code=mail_code, **kwargs) @property @@ -38,6 +39,11 @@ class MailEditingSubView(object): def return_render(self): self.context['form'] = self.mail_form + self.context['header_template'] = self.header_template + if hasattr(self.mail_form, 'instance') and self.mail_form.instance: + self.context['object'] = self.mail_form.instance + else: + self.context['object'] = None return render(self.request, self.template_name, self.context) diff --git a/mails/widgets.py b/mails/widgets.py index f9cfaf114b35723693da4d54e6d187cd2967829a..d13bcf86bc4f2a7111d0cfc96f5d0e5af5ab4f53 100644 --- a/mails/widgets.py +++ b/mails/widgets.py @@ -52,9 +52,8 @@ class SummernoteEditor(widgets.Textarea): def trigger_summernote(self, el_id, options): str = """ <script type='text/javascript'> - var $ = jQuery; - $(document).ready(function() { - $('#%s').summernote(%s) + $(function() { + $('#%s').summernote(%s); }); </script>""" % (el_id, options) return str @@ -66,7 +65,7 @@ class SummernoteEditor(widgets.Textarea): } js = ('//cdnjs.cloudflare.com/ajax/libs/summernote/0.8.8/summernote-bs4.js',) - if self.include_jquery: - js = ('//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js',) + js + # if self.include_jquery: + # js = ('//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js',) + js return Media(css=css, js=js) diff --git a/partners/models.py b/partners/models.py index 966a782317001e39eb221f954b9a3b4e03110657..d8c0b21da83faa3fade57d4fcbbf8ffd902c07f7 100644 --- a/partners/models.py +++ b/partners/models.py @@ -14,22 +14,20 @@ from django.urls import reverse from django_countries.fields import CountryField -from .constants import PARTNER_KINDS, PARTNER_STATUS, CONSORTIUM_STATUS, MEMBERSHIP_DURATION,\ - PROSPECTIVE_PARTNER_STATUS, PROSPECTIVE_PARTNER_EVENTS, PARTNER_EVENTS,\ - MEMBERSHIP_AGREEMENT_STATUS, PROSPECTIVE_PARTNER_ADDED,\ - PARTNER_KIND_UNI_LIBRARY -from .constants import PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT,\ - PROSPECTIVE_PARTNER_APPROACHED,\ - PROSPECTIVE_PARTNER_EVENT_INITIATE_NEGOTIATION,\ - PROSPECTIVE_PARTNER_NEGOTIATING,\ - PROSPECTIVE_PARTNER_EVENT_MARKED_AS_UNINTERESTED,\ - PROSPECTIVE_PARTNER_UNINTERESTED,\ - PROSPECTIVE_PARTNER_EVENT_PROMOTED,\ - PROSPECTIVE_PARTNER_PROCESSED, CONTACT_TYPES,\ - PARTNER_INITIATED, REQUEST_STATUSES, REQUEST_INITIATED - -from .managers import MembershipAgreementManager, ProspectivePartnerManager, PartnerManager,\ - ContactRequestManager, PartnersAttachmentManager +from .constants import ( + PARTNER_KINDS, PARTNER_STATUS, CONSORTIUM_STATUS, MEMBERSHIP_DURATION, PARTNER_EVENTS, + PROSPECTIVE_PARTNER_STATUS, PROSPECTIVE_PARTNER_EVENTS, MEMBERSHIP_AGREEMENT_STATUS, + PROSPECTIVE_PARTNER_ADDED, PARTNER_KIND_UNI_LIBRARY) +from .constants import ( + PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT, PROSPECTIVE_PARTNER_APPROACHED, PARTNER_INITIATED, + PROSPECTIVE_PARTNER_EVENT_INITIATE_NEGOTIATION, PROSPECTIVE_PARTNER_PROCESSED, CONTACT_TYPES, + PROSPECTIVE_PARTNER_NEGOTIATING, PROSPECTIVE_PARTNER_EVENT_MARKED_AS_UNINTERESTED, + REQUEST_STATUSES, PROSPECTIVE_PARTNER_UNINTERESTED, PROSPECTIVE_PARTNER_EVENT_PROMOTED, + REQUEST_INITIATED) + +from .managers import ( + MembershipAgreementManager, ProspectivePartnerManager, PartnerManager, ContactRequestManager, + PartnersAttachmentManager) from scipost.constants import TITLE_CHOICES from scipost.fields import ChoiceArrayField @@ -44,9 +42,8 @@ now = timezone.now() ######################## class ProspectivePartner(models.Model): - """ - Created from the membership_request page, after submitting a query form. - """ + """A prospect Partner is a Partner without explicit contract with SciPost yet.""" + kind = models.CharField(max_length=32, choices=PARTNER_KINDS, default=PARTNER_KIND_UNI_LIBRARY) institution_name = models.CharField(max_length=256) country = CountryField() @@ -62,6 +59,11 @@ class ProspectivePartner(models.Model): self.date_received.strftime("%Y-%m-%d"), self.get_status_display()) + @property + def is_promoted_to_partner(self): + """Check if Prospect is already known to be a Partner.""" + return self.status == PROSPECTIVE_PARTNER_PROCESSED + def update_status_from_event(self, event): if event == PROSPECTIVE_PARTNER_EVENT_EMAIL_SENT: self.status = PROSPECTIVE_PARTNER_APPROACHED diff --git a/partners/templates/partners/_prospective_partner_card.html b/partners/templates/partners/_prospective_partner_card.html index 48c903504c317ae88d07ef63fdbd60c621bbd770..9a56f10cd941f5f431d31d4735cacc6ce8ea2402 100644 --- a/partners/templates/partners/_prospective_partner_card.html +++ b/partners/templates/partners/_prospective_partner_card.html @@ -70,10 +70,12 @@ <input type="submit" name="submit" value="Submit" class="btn btn-outline-secondary"> </form> - <h3>Partner status</h3> - <ul> - <li><a href="{% url 'partners:promote_prospartner' pp.id %}">Upgrade prospect to partner</a></li> - </ul> + {% if not pp.is_promoted_to_partner %} + <h3>Partner status</h3> + <ul> + <li><a href="{% url 'partners:promote_prospartner' pp.id %}">Upgrade prospect to partner</a></li> + </ul> + {% endif %} </div> </div> </div> diff --git a/partners/views.py b/partners/views.py index a17405729386aea2af58cb53b24854e185c9e4d0..9c5bf531d0eddab20e19d08ebb22f4480caff132 100644 --- a/partners/views.py +++ b/partners/views.py @@ -47,10 +47,11 @@ def supporting_partners(request): @login_required @permission_required('scipost.can_read_partner_page', return_403=True) def dashboard(request): - ''' + """Administration page for Partners and Prospective Partners. + This page is meant as a personal page for Partners, where they will for example be able to read their personal data and agreements. - ''' + """ context = {} try: context['personal_agreements'] = (MembershipAgreement.objects.open_to_partner() @@ -62,8 +63,8 @@ def dashboard(request): context['contact_requests_count'] = ContactRequest.objects.awaiting_processing().count() context['inactivate_contacts_count'] = Contact.objects.filter(user__is_active=False).count() context['partners'] = Partner.objects.all() - context['prospective_partners'] = (ProspectivePartner.objects.not_yet_partner() - .order_by('country', 'institution_name')) + context['prospective_partners'] = ProspectivePartner.objects.order_by( + 'country', 'institution_name') context['ppevent_form'] = ProspectivePartnerEventForm() context['agreements'] = MembershipAgreement.objects.order_by('date_requested') return render(request, 'partners/dashboard.html', context) diff --git a/scipost/static/scipost/info/AnnualReports/AnnualReport_2015.pdf b/scipost/static/scipost/info/AnnualReports/AnnualReport_2015.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6c6473508a5e182cf496f627afd2e966ecbc0b5b Binary files /dev/null and b/scipost/static/scipost/info/AnnualReports/AnnualReport_2015.pdf differ diff --git a/scipost/static/scipost/info/AnnualReports/AnnualReport_2016.pdf b/scipost/static/scipost/info/AnnualReports/AnnualReport_2016.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6bd811577587c7a1d60dcf8827fb20ba29a5b824 Binary files /dev/null and b/scipost/static/scipost/info/AnnualReports/AnnualReport_2016.pdf differ diff --git a/scipost/static/scipost/info/AnnualReports/AnnualReport_2017.pdf b/scipost/static/scipost/info/AnnualReports/AnnualReport_2017.pdf new file mode 100644 index 0000000000000000000000000000000000000000..43863e00252e7fb34366a408d0836ec17821fa3d Binary files /dev/null and b/scipost/static/scipost/info/AnnualReports/AnnualReport_2017.pdf differ diff --git a/scipost/templates/partials/scipost/personal_page/account.html b/scipost/templates/partials/scipost/personal_page/account.html index bfda86979026a266428a272d69dc8e4e5b2b9d1e..43e350ba7295fd8f3707fe43756b793d40a18520 100644 --- a/scipost/templates/partials/scipost/personal_page/account.html +++ b/scipost/templates/partials/scipost/personal_page/account.html @@ -102,6 +102,15 @@ {% if fellowship.guest %} (Guest Fellowship) + <br> + Your Proceedings: + <ul> + {% for proc in fellowship.proceedings.all %} + <li>{{ proc }}</li> + {% empty %} + <li><em>No proceedings assigned yet.</em></li> + {% endfor %} + </ul> {% else %} (Regular Fellowship) {% endif %} diff --git a/scipost/templates/scipost/bare_base.html b/scipost/templates/scipost/bare_base.html index fbfb7b288ed8f36a1e814836c0eb22981202e85e..5efb4b3aed589d63858c7c6cde5cadd1d0a8d2bf 100644 --- a/scipost/templates/scipost/bare_base.html +++ b/scipost/templates/scipost/bare_base.html @@ -9,7 +9,7 @@ <link href="https://fonts.googleapis.com/css?family=Merriweather+Sans:300,400,700" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="{% static 'scipost/SciPost.css' %}" /> <link rel="stylesheet" type="text/css" href="{% static 'fa/css/font-awesome.min.css' %}" /> - <script async src="https://code.jquery.com/jquery-2.2.0.min.js"></script> + <script async src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> <script async src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> {% render_bundle 'main' 'css' %} diff --git a/scipost/templates/scipost/foundation.html b/scipost/templates/scipost/foundation.html index 75430efccb88624bb861a053398ca155faa504e5..d541dee897dfa5f9fb7b39264c77ca27a7186349 100644 --- a/scipost/templates/scipost/foundation.html +++ b/scipost/templates/scipost/foundation.html @@ -71,16 +71,6 @@ </div> </div> - <div class="card bg-white border-0"> - <div class="card-body"> - <h2 class="highlight">Registration</h2> - <p class="px-2"> - Dutch Chamber of Commerce nr 65280083.</br> - RSIN 856049487.<br> - <a href="{% static 'scipost/info/uittreksel_Stichting_SciPost.pdf' %}">Registration extract</a>. - </p> - </div> - </div> </div> </div> </div> @@ -88,23 +78,33 @@ <div class="row"> <div class="col-12"> <div class="card-deck"> +<!-- <div class="card bg-white border-0"> <div class="card-body"> - <h2 class="highlight">Registration</h2> + <h2 class="highlight">Yearly Reports</h2> + <p class="px-2">2016 (to be published)</p> </div> </div> - +--> <div class="card bg-white border-0"> <div class="card-body"> - <h2 class="highlight">Yearly Reports</h2> - <p class="px-2">2016 (to be published)</p> + <h2 class="highlight">Registration</h2> + <p class="px-2"> + Dutch Chamber of Commerce nr 65280083.</br> + RSIN 856049487.<br> + <a href="{% static 'scipost/info/uittreksel_Stichting_SciPost.pdf' %}">Registration extract</a>. + </p> </div> </div> <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Financial Reports</h2> - <p class="px-2">2016-7 (to be published)</p> + <ul> + <li><a href="{% static 'scipost/info/AnnualReports/AnnualReport_2015.pdf' %}">Annual Report 2015</a></li> + <li><a href="{% static 'scipost/info/AnnualReports/AnnualReport_2016.pdf' %}">Annual Report 2016</a></li> + <li><a href="{% static 'scipost/info/AnnualReports/AnnualReport_2017.pdf' %}">Annual Report 2017</a></li> + </ul> </div> </div> </div> diff --git a/submissions/forms.py b/submissions/forms.py index c07f76b1fe3bd5a4ad07c51f5b3455930140ee98..7aa45b91c4a90757b431f9743a3f1e89715d7c64 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -24,7 +24,7 @@ from .models import ( from common.helpers import get_new_secrets_key from colleges.models import Fellowship from invitations.models import RegistrationInvitation -from journals.constants import SCIPOST_JOURNAL_PHYSICS_PROC +from journals.constants import SCIPOST_JOURNAL_PHYSICS_PROC, SCIPOST_JOURNAL_PHYSICS from scipost.constants import SCIPOST_SUBJECT_AREAS, INVITATION_REFEREEING from scipost.services import ArxivCaller from scipost.models import Contributor @@ -290,6 +290,7 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): del self.fields['proceedings'] # Update placeholder for the other fields + self.fields['submission_type'].required = False self.fields['arxiv_link'].widget.attrs.update({ 'placeholder': 'ex.: arxiv.org/abs/1234.56789v1'}) self.fields['abstract'].widget.attrs.update({'cols': 100}) @@ -322,9 +323,8 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): return cleaned_data def clean_author_list(self): - """ - Important check! - + """Check if author list matches the Contributor submitting. + The submitting user must be an author of the submission. Also possibly may be extended to check permissions and give ultimate submission power to certain user groups. @@ -336,12 +336,20 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): raise forms.ValidationError(error_message, code='not_an_author') return author_list + def clean_submission_type(self): + """Validate Submission type. + + The SciPost Physics journal requires a Submission type to be specified. + """ + submission_type = self.cleaned_data['submission_type'] + journal = self.cleaned_data['submitted_to_journal'] + if journal == SCIPOST_JOURNAL_PHYSICS and not submission_type: + self.add_error('submission_type', 'Please specify the submission type.') + return submission_type + @transaction.atomic def copy_and_save_data_from_resubmission(self, submission): - """ - Fill given Submission with data coming from last_submission in the SubmissionChecks - blueprint. - """ + """Fill given Submission with data coming from last_submission.""" if not self.last_submission: raise Submission.DoesNotExist diff --git a/submissions/templates/partials/submissions/admin/editorial_assignment_failed.html b/submissions/templates/partials/submissions/admin/editorial_assignment_failed.html new file mode 100644 index 0000000000000000000000000000000000000000..09bd150d83dac7dbc9371018115fe3498d284cc6 --- /dev/null +++ b/submissions/templates/partials/submissions/admin/editorial_assignment_failed.html @@ -0,0 +1,13 @@ +<h1 class="highlight">Assignment has failed for Submission</h1> +<h3>Submission details</h3> +{% include 'partials/submissions/submission_summary.html' with submission=object %} + +<br> +<h3>Current EIC assignment requests:</h3> +<ul> + {% for assignment in object.editorial_assignments.all %} + {% include 'partials/submissions/pool/assignment_info.html' with assignment=assignment %} + {% empty %} + <li>No assignment requests have been sent</li> + {% endfor %} +</ul> diff --git a/submissions/templates/partials/submissions/arxiv_queryresult.html b/submissions/templates/partials/submissions/arxiv_queryresult.html index b6cb2a65fb2af2b3ad5d0c36306ce6db5f622542..e469a0320a9387051903a8d4dbccebba92d00d64 100644 --- a/submissions/templates/partials/submissions/arxiv_queryresult.html +++ b/submissions/templates/partials/submissions/arxiv_queryresult.html @@ -1,12 +1,12 @@ <div class="card-body"> <h3 class="card-title">{{ item.title }}</h3> <div class="card-text"> - <div class="authors mb-2" id="arxiv_authors_{{ id }}" style="display: none;"> + <a href="javascript:;" data-toggle="toggle" data-target="#arxiv_authors_{{ id }}_{{ id2 }}">Toggle authors</a> · <a href="{{ item.link }}" target="_blank">{{ item.id }}</a> + <div class="authors mt-2" id="arxiv_authors_{{ id }}_{{ id2 }}" style="display: none;"> {% for author in item.authors %} {{ author.name }}{% if not forloop.last %},{% endif %} {% endfor %} </div> - <a href="javascript:;" data-toggle="toggle" data-target="#arxiv_authors_{{ id }}">Toggle authors</a> · <a href="{{ item.link }}" target="_blank">{{ item.id }}</a> </div> <p class="card-text text-muted">Published: {{ item.published }}</p> </div> diff --git a/submissions/templates/submissions/admin/editorial_assignment_failed.html b/submissions/templates/submissions/admin/editorial_assignment_failed.html deleted file mode 100644 index cd2931bea482477f5fd6ce8777d9a2cb50db2a52..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/admin/editorial_assignment_failed.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends 'scipost/base.html' %} - -{% load bootstrap %} - -{% block pagetitle %}: assignment failed (ack){% endblock pagetitle %} - -{% block content %} - -<h1>Assignment has failed for Submission</h1> -<p>{{ submission.title }} by {{ submission.author_list }}.</p> -<p>Please add comments on the Submission in this box.</p> -<form action="{% url 'submissions:assignment_failed' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="POST"> - {% csrf_token %} - {{ form|bootstrap }} - <input type="submit" name="Submit" class="btn btn-primary" /> -</form> - -{% endblock content %} diff --git a/submissions/templates/submissions/admin/editorial_assignment_form.html b/submissions/templates/submissions/admin/editorial_assignment_form.html index 0761db76ba37f126cea40b4f53ae96df497623da..a437401f49b0a43daad1775e9280f065fb82cef9 100644 --- a/submissions/templates/submissions/admin/editorial_assignment_form.html +++ b/submissions/templates/submissions/admin/editorial_assignment_form.html @@ -66,7 +66,7 @@ <div class="row"> <div class="col-12"> {% if coauthorships %} - <div class="card card-outline-danger"> + <div class="card border-danger"> <div class="card-body"> <h3 class="card-title text-danger">The system identified the following potential coauthorships (from arXiv database)</h3> <p class="card-text text-danger">(only up to 5 most recent shown; if within the last 3 years, referee is disqualified):</p> @@ -81,7 +81,7 @@ </li> {% for entry in entries %} <li class="list-group-item"> - {% include 'partials/submissions/arxiv_queryresult.html' with item=entry id=forloop.counter %} + {% include 'partials/submissions/arxiv_queryresult.html' with item=entry id=forloop.counter id2=forloop.parentloop.counter %} </li> {% endfor %} {% endfor %} diff --git a/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html b/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html index 8f9b0781085769edc12de0b7bf0536852e1bd677..b7ff99ca46377deb652e6f999885ea51cf5e2f5a 100644 --- a/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html +++ b/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html @@ -49,7 +49,7 @@ <div class="row"> <div class="col-12"> {% if coauthorships %} - <div class="card card-outline-danger"> + <div class="card border-danger"> <div class="card-body"> <h3 class="card-title text-danger">The system identified the following potential coauthorships (from arXiv database)</h3> <p class="card-text text-danger">(only up to 5 most recent shown; if within the last 3 years, referee is disqualified):</p> @@ -60,11 +60,11 @@ <li class="list-group-item pt-3"> <div class="card-content"> <h3>For Fellow: {{ author }}</h3> - </div>{{ value}} + </div> </li> {% for entry in entries %} <li class="list-group-item"> - {% include 'partials/submissions/arxiv_queryresult.html' with item=entry id=forloop.counter %} + {% include 'partials/submissions/arxiv_queryresult.html' with item=entry id=forloop.counter id2=forloop.parentloop.counter %} </li> {% endfor %} {% endfor %} diff --git a/submissions/templates/submissions/referee_form.html b/submissions/templates/submissions/referee_form.html index 8fae92385d4bde0416a0f6bffbb356bec371811f..9935f079af18f9a31efc4747dceeb75c49d1f2e9 100644 --- a/submissions/templates/submissions/referee_form.html +++ b/submissions/templates/submissions/referee_form.html @@ -52,16 +52,16 @@ {% if queryresults.entries %} <div class="row"> <div class="col-12"> - <div class="card card-outline-danger"> + <div class="card border-danger"> <div class="card-body"> <h3 class="card-title text-danger">The system identified the following potential coauthorships (from arXiv database)</h3> <p class="card-text text-danger">(only up to 5 most recent shown; if within the last 3 years, referee is disqualified):</p> </div> <div class="card-body"> - <ul class="list-group list-group-flush"> + <ul class="list-group list-group-flush px-0"> {% for entry in queryresults.entries %} <li class="list-group-item"> - {% include 'partials/submissions/arxiv_queryresult.html' with item=entry %} + {% include 'partials/submissions/arxiv_queryresult.html' with item=entry id=forloop.counter id2=0 %} </li> {% endfor %} </ul> diff --git a/submissions/utils.py b/submissions/utils.py index 44115064ba9bfc12aced5a0b3e6d217b9f1b7404..5098fbc6b3e7dc5dad7a6b5315bd1bcf9439b55e 100644 --- a/submissions/utils.py +++ b/submissions/utils.py @@ -569,68 +569,6 @@ class SubmissionUtils(BaseMailUtil): emailmessage.attach_alternative(html_version, 'text/html') emailmessage.send(fail_silently=False) - @classmethod - def assignment_failed_email_authors(cls): - """ Requires loading 'submission' attribute. """ - email_text = ('Dear ' + cls.submission.submitted_by.get_title_display() + ' ' - + cls.submission.submitted_by.user.last_name - + ', \n\nYour recent Submission to SciPost,\n\n' - + cls.submission.title + ' by ' + cls.submission.author_list - + '\n\nhas unfortunately not passed the pre-screening stage. ' - 'We therefore regret to inform you that we will not ' - 'process your paper further towards publication, and that you ' - 'are now free to send your manuscript to an alternative journal.') - if len(cls.personal_message) > 3: - email_text += '\n\n' + cls.personal_message - email_text += ('\n\nWe nonetheless thank you very much for your contribution.' - '\n\nSincerely,' + - '\n\nThe SciPost Team.') - email_text_html = ( - '<p>Dear {{ title }} {{ last_name }},</p>' - '<p>Your recent Submission to SciPost,</p>' - '<p>{{ sub_title }}</p>' - '\n<p>by {{ author_list }}</p>' - '\n<p>has unfortunately not passed the pre-screening stage. ' - 'We therefore regret to inform you that we will not ' - 'process your paper further towards publication, and that you ' - 'are now free to send your manuscript to an alternative journal.</p>') - if len(cls.personal_message) > 3: - email_text_html += '{{ personal_message|linebreaks }}' - email_text_html += ( - '<p>We nonetheless thank you very much for your contribution.</p>' - '<p>Sincerely,</p>' - '<p>The SciPost Team.</p>') - email_context = { - 'title': cls.submission.submitted_by.get_title_display(), - 'last_name': cls.submission.submitted_by.user.last_name, - 'sub_title': cls.submission.title, - 'author_list': cls.submission.author_list, - 'personal_message': cls.personal_message, - } - email_text_html += '<br/>' + EMAIL_FOOTER - html_template = Template(email_text_html) - html_version = html_template.render(Context(email_context)) - emailmessage = EmailMultiAlternatives( - 'SciPost: pre-screening not passed', email_text, - 'SciPost Editorial Admin <submissions@scipost.org>', - [cls.submission.submitted_by.user.email], - bcc=['submissions@scipost.org'], - reply_to=['submissions@scipost.org']) - emailmessage.attach_alternative(html_version, 'text/html') - emailmessage.send(fail_silently=False) - - @classmethod - def send_refereeing_invitation_email(cls): - """ - This method is called by send_refereeing_invitation in submissions/views. - It is used when the referee is already a registered contributor. - If a referee is not yet registered, the method recruit_referee is used - instead, which calls the send_registration_email method in scipost/utils. - Requires loading 'invitation' attribute. - """ - raise DeprecationWarning(('Use new mails.views.MailEditingSubView() with code' - ' `submission_referee_invite` instead')) - @classmethod def send_unreg_ref_reminder_email(cls): """ diff --git a/submissions/views.py b/submissions/views.py index bac948e24945f6506ea4fb62dea10bf0309bdfd8..3c1c2e08f13e5656a35d70ce0adb45d460857489 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -1,4 +1,4 @@ -__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" +ip__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" __license__ = "AGPL v3" @@ -25,7 +25,7 @@ from django.views.generic.list import ListView from guardian.shortcuts import assign_perm from .constants import STATUS_VETTED, STATUS_EIC_ASSIGNED,\ - SUBMISSION_STATUS_PUBLICLY_INVISIBLE, SUBMISSION_STATUS,\ + SUBMISSION_STATUS_PUBLICLY_INVISIBLE, SUBMISSION_STATUS, STATUS_ASSIGNMENT_FAILED,\ STATUS_DRAFT, CYCLE_DIRECT_REC, STATUS_VOTING_IN_PREPARATION,\ STATUS_PUT_TO_EC_VOTING from .models import Submission, EICRecommendation, EditorialAssignment,\ @@ -574,14 +574,18 @@ def volunteer_as_EIC(request, arxiv_identifier_w_vn_nr): deadline += datetime.timedelta(days=28) # Update Submission data - submission.status = STATUS_EIC_ASSIGNED - submission.editor_in_charge = contributor - submission.open_for_reporting = True - submission.reporting_deadline = deadline - submission.open_for_commenting = True - submission.save() - submission.touch() - + Submission.objects.filter(id=submission.id).update( + status=STATUS_EIC_ASSIGNED, + editor_in_charge=contributor, + open_for_reporting=True, + reporting_deadline=deadline, + open_for_commenting=True, + latest_activity=timezone.now()) + + # Deprecate old Editorial Assignments + EditorialAssignment.objects.filter(submission=submission).open().update(deprecated=True) + + # Send emails to EIC and authors regarding the EIC assignment. SubmissionUtils.load({'assignment': assignment}) SubmissionUtils.deprecate_other_assignments() SubmissionUtils.send_EIC_appointment_email() @@ -599,41 +603,40 @@ def volunteer_as_EIC(request, arxiv_identifier_w_vn_nr): @permission_required('scipost.can_assign_submissions', raise_exception=True) @transaction.atomic def assignment_failed(request, arxiv_identifier_w_vn_nr): + """Reject a Submission in pre-screening. + + No Editorial Fellow has accepted or volunteered to become Editor-in-charge., hence the + Submission is rejected. An Editorial Administrator can access this view from the Pool. """ - 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.objects.pool(request.user), + submission = get_object_or_404(Submission.objects.pool(request.user).prescreening(), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) - if request.method == 'POST': - form = ModifyPersonalMessageForm(request.POST) - if form.is_valid(): - submission.status = 'assignment_failed' - submission.latest_activity = timezone.now() - submission.save() - SubmissionUtils.load({'submission': submission, - 'personal_message': form.cleaned_data['personal_message']}) - SubmissionUtils.deprecate_all_assignments() - SubmissionUtils.assignment_failed_email_authors() - context = {'ack_header': ('Submission ' + submission.arxiv_identifier_w_vn_nr + - ' has failed pre-screening and been rejected. ' - 'Authors have been informed by email.'), - 'followup_message': 'Return to the ', - 'followup_link': reverse('submissions:pool'), - 'followup_link_label': 'Submissions pool'} - return render(request, 'scipost/acknowledgement.html', context) + + mail_request = MailEditingSubView( + request, mail_code='submissions_assignment_failed', instance=submission, + header_template='partials/submissions/admin/editorial_assignment_failed.html') + if mail_request.is_valid(): + # Deprecate old Editorial Assignments + EditorialAssignment.objects.filter(submission=submission).open().update(deprecated=True) + + # Update status of Submission + submission.touch() + Submission.objects.filter(id=submission.id).update(status=STATUS_ASSIGNMENT_FAILED) + + messages.success( + request, 'Submission {arxiv} has failed pre-screening and been rejected.'.format( + arxiv=submission.arxiv_identifier_w_vn_nr)) + messages.success(request, 'Authors have been informed by email.') + mail_request.send() + return redirect(reverse('submissions:pool')) else: - form = ModifyPersonalMessageForm() - context = {'submission': submission, - 'form': form} - return render(request, 'submissions/admin/editorial_assignment_failed.html', context) + return mail_request.return_render() @login_required @fellowship_required() def assignments(request): - """ + """List editorial tasks for a Fellow. + This page provides a Fellow with an explicit task list of editorial actions which should be undertaken. """ @@ -654,10 +657,10 @@ def assignments(request): @login_required @fellowship_or_admin_required() def editorial_page(request, arxiv_identifier_w_vn_nr): - """ - The central page for the EIC to manage all its Editorial duties. + """Detail page of a Submission its editorial tasks. - Accessible for: Editor-in-charge and Editorial Administration + The central page for the Editor-in-charge to manage all its Editorial duties. It's accessible + for both the Editor-in-charge of the Submission and the Editorial Administration. """ submission = get_object_or_404(Submission.objects.pool_full(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr)