diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py index d5d7a8f606ab5cd27ab52f6036260623c1fe7cac..44532bc63c162b25e9049c152ba72e079bfeee4a 100644 --- a/SciPost_v1/settings/base.py +++ b/SciPost_v1/settings/base.py @@ -84,6 +84,7 @@ INSTALLED_APPS = ( 'haystack', 'rest_framework', 'sphinxdoc', + 'colleges', 'commentaries', 'comments', 'finances', @@ -96,6 +97,7 @@ INSTALLED_APPS = ( 'submissions', 'theses', 'virtualmeetings', + 'proceedings', 'production', 'partners', 'funders', diff --git a/SciPost_v1/urls.py b/SciPost_v1/urls.py index cd3462f1bd2cd18e7e145be4bda23e1cc41d080b..5e06ce57cc97bd5caf2b866a23a16bbb4ccaf333 100644 --- a/SciPost_v1/urls.py +++ b/SciPost_v1/urls.py @@ -29,6 +29,7 @@ urlpatterns = [ url(r'^10.21468/%s/' % JOURNAL_REGEX, include('journals.urls.journal', namespace="journal")), url(r'^%s/' % JOURNAL_REGEX, include('journals.urls.journal', namespace="_journal")), url(r'^', include('scipost.urls', namespace="scipost")), + url(r'^colleges/', include('colleges.urls', namespace="colleges")), url(r'^commentaries/', include('commentaries.urls', namespace="commentaries")), url(r'^commentary/', include('commentaries.urls', namespace="_commentaries")), url(r'^comments/', include('comments.urls', namespace="comments")), @@ -44,6 +45,7 @@ urlpatterns = [ url(r'^news/', include('news.urls', namespace="news")), url(r'^notifications/', include('notifications.urls', namespace="notifications")), url(r'^petitions/', include('petitions.urls', namespace="petitions")), + url(r'^proceedings/', include('proceedings.urls', namespace="proceedings")), url(r'^production/', include('production.urls', namespace="production")), url(r'^partners/', include('partners.urls', namespace="partners")), url(r'^stats/', include('stats.urls', namespace="stats")), diff --git a/colleges/__init__.py b/colleges/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/colleges/admin.py b/colleges/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..d81df17fd46f1abefbc1a7fc464a409d6550f6c2 --- /dev/null +++ b/colleges/admin.py @@ -0,0 +1,18 @@ +from django.contrib import admin + +from .models import Fellowship + + +def fellowhip_is_active(fellowship): + return fellowship.is_active() + + +class FellowshipAdmin(admin.ModelAdmin): + search_fields = ['contributor__last_name', 'contributor__first_name'] + list_display = ('__str__', 'guest', fellowhip_is_active, ) + list_filter = ('guest',) + fellowhip_is_active.boolean = True + date_hierarchy = 'created' + + +admin.site.register(Fellowship, FellowshipAdmin) diff --git a/colleges/apps.py b/colleges/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..e1d74cff7d6248bb7702cad64f2ba1c406061042 --- /dev/null +++ b/colleges/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CollegesConfig(AppConfig): + name = 'colleges' diff --git a/colleges/forms.py b/colleges/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..3de926d4c0b099495f19b5feb73e430ab320956c --- /dev/null +++ b/colleges/forms.py @@ -0,0 +1,169 @@ +import datetime + +from django import forms + +from proceedings.models import Proceedings +from submissions.models import Submission +from scipost.models import Contributor + +from .models import Fellowship + + +class AddFellowshipForm(forms.ModelForm): + class Meta: + model = Fellowship + fields = ( + 'guest', + 'contributor', + 'start_date', + 'until_date', + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['contributor'].queryset = Contributor.objects.fellows() + self.fields['contributor'].label = "Fellow" + + def clean(self): + start = self.cleaned_data.get('start_date') + until = self.cleaned_data.get('until_date') + if start and until: + if until <= start: + self.add_error('until_date', 'The given dates are not in chronological order.') + + +class FellowshipForm(forms.ModelForm): + class Meta: + model = Fellowship + fields = ( + 'guest', + 'start_date', + 'until_date', + ) + + def clean(self): + start = self.cleaned_data.get('start_date') + until = self.cleaned_data.get('until_date') + if start and until: + if until <= start: + self.add_error('until_date', 'The given dates are not in chronological order.') + + +class FellowshipTerminateForm(forms.ModelForm): + class Meta: + model = Fellowship + fields = [] + + def save(self): + today = datetime.date.today() + fellowship = self.instance + if fellowship.until_date > today: + fellowship.until_date = today + return fellowship.save() + + +class FellowshipRemoveSubmissionForm(forms.ModelForm): + """ + Use this form in admin-accessible views only! It could possibly reveal the + identity of the Editor-in-charge! + """ + class Meta: + model = Fellowship + fields = [] + + def __init__(self, *args, **kwargs): + self.submission = kwargs.pop('submission') + super().__init__(*args, **kwargs) + + def clean(self): + if self.submission.editor_in_charge == self.instance.contributor: + self.add_error(None, ('Submission cannot be removed as the Fellow is' + ' Editor-in-charge of this Submission.')) + + def save(self): + fellowship = self.instance + fellowship.pool.remove(self.submission) + return fellowship + + +class FellowshipAddSubmissionForm(forms.ModelForm): + submission = forms.ModelChoiceField(queryset=None, to_field_name='arxiv_identifier_w_vn_nr', + empty_label="Please choose the Submission to add to the pool") + + class Meta: + model = Fellowship + fields = [] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + pool = self.instance.pool.values_list('id', flat=True) + self.fields['submission'].queryset = Submission.objects.exclude(id__in=pool) + + def save(self): + submission = self.cleaned_data['submission'] + fellowship = self.instance + fellowship.pool.add(submission) + return fellowship + + +class SubmissionAddFellowshipForm(forms.ModelForm): + fellowship = forms.ModelChoiceField(queryset=None, to_field_name='id', + empty_label="Please choose the Fellow to add to the Pool") + + class Meta: + model = Submission + fields = [] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + pool = self.instance.fellows.values_list('id', flat=True) + self.fields['fellowship'].queryset = Fellowship.objects.active().exclude(id__in=pool) + + def save(self): + fellowship = self.cleaned_data['fellowship'] + submission = self.instance + submission.fellows.add(fellowship) + return submission + + +class FellowshipRemoveProceedingsForm(forms.ModelForm): + """ + Use this form in admin-accessible views only! It could possibly reveal the + identity of the Editor-in-charge! + """ + class Meta: + model = Fellowship + fields = [] + + def __init__(self, *args, **kwargs): + self.proceedings = kwargs.pop('proceedings') + super().__init__(*args, **kwargs) + + def clean(self): + if self.proceedings.lead_fellow == self.instance: + self.add_error(None, 'Fellowship cannot be removed as it is assigned as lead fellow.') + + def save(self): + fellowship = self.instance + self.proceedings.fellowships.remove(fellowship) + return fellowship + + +class FellowshipAddProceedingsForm(forms.ModelForm): + proceedings = forms.ModelChoiceField(queryset=None, to_field_name='id', + empty_label="Please choose the Proceedings to add to the Pool") + + class Meta: + model = Fellowship + fields = [] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + proceedings = self.instance.proceedings.values_list('id', flat=True) + self.fields['proceedings'].queryset = Proceedings.objects.exclude(id__in=proceedings) + + def save(self): + proceedings = self.cleaned_data['proceedings'] + fellowship = self.instance + proceedings.fellowships.add(fellowship) + return fellowship diff --git a/colleges/managers.py b/colleges/managers.py new file mode 100644 index 0000000000000000000000000000000000000000..5bea48f0ce53f87bbeea382ffda04417841f5969 --- /dev/null +++ b/colleges/managers.py @@ -0,0 +1,42 @@ +import datetime + +from django.db import models +from django.db.models import Q + + +class FellowQuerySet(models.QuerySet): + def guests(self): + return self.filter(guest=True) + + def regular(self): + return self.filter(guest=False) + + def active(self): + today = datetime.date.today() + return self.filter( + Q(start_date__lte=today, until_date__isnull=True) | + Q(start_date__isnull=True, until_date__gte=today) | + Q(start_date__lte=today, until_date__gte=today) | + Q(start_date__isnull=True, until_date__isnull=True) + ).order_by('contributor__user__last_name') + + def return_active_for_submission(self, submission): + """ + This method returns a *list* of Fellowships that passed the 'author-check' for + a specific submission. + """ + try: + qs = self.exclude(contributor__in=submission.authors.all()).active() + false_claims = submission.authors_false_claims.all() + author_list = submission.author_list.lower() + fellowships = [] + for fellowship in qs: + contributor = fellowship.contributor + user = contributor.user + if user.last_name.lower() in author_list and contributor not in false_claims: + continue + + fellowships.append(fellowship) + return fellowships + except AttributeError: + return [] diff --git a/colleges/migrations/0001_initial.py b/colleges/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..d7f01c265d829fef68276f3a03f7f19d71f5accf --- /dev/null +++ b/colleges/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-20 07:00 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import scipost.db.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('scipost', '0065_authorshipclaim_publication'), + ] + + operations = [ + migrations.CreateModel( + name='Fellowship', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('latest_activity', scipost.db.fields.AutoDateTimeField(blank=True, default=django.utils.timezone.now, editable=False)), + ('start_date', models.DateField(blank=True, null=True)), + ('until_date', models.DateField(blank=True, null=True)), + ('guest', models.BooleanField(default=False, verbose_name='Guest Fellowship')), + ('contributor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fellowships', to='scipost.Contributor')), + ], + ), + migrations.AlterUniqueTogether( + name='fellowship', + unique_together=set([('contributor', 'start_date', 'until_date')]), + ), + ] diff --git a/colleges/migrations/0002_auto_20171020_0931.py b/colleges/migrations/0002_auto_20171020_0931.py new file mode 100644 index 0000000000000000000000000000000000000000..c5ba871e08ad7325de9776d50878f8233e10b308 --- /dev/null +++ b/colleges/migrations/0002_auto_20171020_0931.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-20 07:31 +from __future__ import unicode_literals + +from django.db import migrations + + +def fill_editorial_college(apps, schema_editor): + Fellowship = apps.get_model('colleges', 'Fellowship') + Contributor = apps.get_model('scipost', 'Contributor') + for contributor in Contributor.objects.filter(user__groups__name='Editorial College'): + Fellowship.objects.get_or_create(contributor=contributor) + + +def return_empty(*args, **kwargs): + return + + +class Migration(migrations.Migration): + + dependencies = [ + ('colleges', '0001_initial'), + ] + + operations = [ + migrations.RunPython(fill_editorial_college, return_empty), + ] diff --git a/colleges/migrations/__init__.py b/colleges/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/colleges/models.py b/colleges/models.py new file mode 100644 index 0000000000000000000000000000000000000000..8455d618ae862896b6646658d2bf3817cd6df31e --- /dev/null +++ b/colleges/models.py @@ -0,0 +1,54 @@ +import datetime + +from django.db import models +from django.urls import reverse + +from scipost.behaviors import TimeStampedModel + +from .managers import FellowQuerySet + + +class Fellowship(TimeStampedModel): + """ + Editorial College Fellowship connecting Editorial College and Contributors, + possibly with a limiting start/until date. + + 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) + until_date = models.DateField(null=True, blank=True) + + guest = models.BooleanField('Guest Fellowship', default=False) + + objects = FellowQuerySet.as_manager() + + class Meta: + unique_together = ('contributor', 'start_date', 'until_date') + + def __str__(self): + _str = self.contributor.__str__() + if self.guest: + _str += ' (guest fellowship)' + return _str + + def get_absolute_url(self): + 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 self.contributor.fellowships.all() + + def is_active(self): + today = datetime.date.today() + if not self.start_date: + if not self.until_date: + return True + return today <= self.until_date + elif not self.until_date: + return today >= self.start_date + return today >= self.start_date and today <= self.until_date diff --git a/colleges/templates/colleges/fellowship_add.html b/colleges/templates/colleges/fellowship_add.html new file mode 100644 index 0000000000000000000000000000000000000000..76f1b2ec8d1c58fcec7019f638503d3bab7fa464 --- /dev/null +++ b/colleges/templates/colleges/fellowship_add.html @@ -0,0 +1,24 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <span class="breadcrumb-item">Add Fellowship</span> +{% endblock %} + +{% block pagetitle %}: Add Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Add Fellowship</h1> + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary" type="submit" value="Add Fellowship"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_details.html b/colleges/templates/colleges/fellowship_details.html new file mode 100644 index 0000000000000000000000000000000000000000..8abb91812d0ec821deacb872a26e7a54f5ea37a5 --- /dev/null +++ b/colleges/templates/colleges/fellowship_details.html @@ -0,0 +1,156 @@ +{% extends 'submissions/admin/base.html' %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <span class="breadcrumb-item">Fellowship details</span> +{% endblock %} + +{% block pagetitle %}: Fellowship details{% endblock pagetitle %} + +{% block content %} + <h1>Fellowship details</h1> + <h2 class="text-primary">{{ fellowship }}</h2> + <br> + + <div class="row"> + <div class="col-md-6"> + <h3>Details</h3> + + <table class="table"> + <tbody> + <tr> + <th>Fellowship ID</th> + <td>{{ fellowship.id }}</td> + </tr> + <tr> + <th>Fellow</th> + <td>{{ fellowship }}</td> + </tr> + <tr> + <th>Discipline</th> + <td>{{ fellowship.contributor.get_discipline_display }}</td> + </tr> + <tr> + <th>Start date</th> + <td>{{ fellowship.start_date|default:'<i>No start date</i>' }}</td> + </tr> + <tr> + <th>End date</th> + <td>{{ fellowship.until_date|default:'<i>No end date</i>' }}</td> + </tr> + <tr> + <th>Pool size</th> + <td>{{ fellowship.pool.count }}</td> + </tr> + <tr> + <th>Type</th> + <td>{{ fellowship.guest|yesno:"Guest fellowship,Regular fellowship"|safe }}</td> + </tr> + </tbody> + </table> + + <form method="post" action="{% url 'colleges:fellowship_terminate' fellowship.id %}" class="d-inline"> + {% csrf_token %} + <button type="submit" class="btn btn-danger">Terminate Fellowship</button> + </form> + <a href="{% url 'colleges:fellowship_edit' fellowship.id %}" class="btn btn-info ml-2">Edit Fellowship</a> + </div> + <div class="col-md-6"> + <h3>All fellowships of this fellow</h3> + + <table class="table"> + <thead> + <tr> + <th>Fellowship ID</th> + <th>Type</th> + <th colspan="2">Date range</th> + </tr> + </thead> + <tbody> + {% for fellowship in fellowship.sibling_fellowships %} + <tr> + <td>{{ fellowship.id }}</td> + <td>{{ fellowship.guest|yesno:"Guest fellowship,Regular fellowship"|safe }}</td> + <td> + {% if fellowship.start_date %} + from {{ fellowship.start_date }} + {% endif %} + {% if fellowship.until_date %} + until {{ fellowship.until_date }} + {% endif %} + {% if not fellowship.start_date and not fellowship.until_date %} + <i>Unlimited</i> + {% endif %} + </td> + <td><a href="{{ fellowship.get_absolute_url }}">See details</a></td> + </tr> + {% endfor %} + </tbody> + </table> + <a href="{% url 'colleges:fellowship_add' %}?contributor={{ fellowship.contributor.id }}">Add new Fellowship for {{ fellowship.contributor }}</a> + </div> + </div> + + {% if fellowship.guest %} + <h3>Proceedings this Guest Fellowship is assigned to</h3> + <table class="table table-hover"> + <thead> + <tr> + <th>Event</th> + <th>Issue</th> + <th>Submissions Open</th> + <th>Submissions Deadline</th> + <th>Submissions Close</th> + <th></th> + </tr> + </thead> + <tbody> + {% for proceedings in fellowship.proceedings.all %} + <tr> + <td>{{ proceedings.event_name }}</td> + <td><a href="{{ proceedings.get_absolute_url }}">{{ proceedings.issue }}</a></td> + <td>{{ proceedings.submissions_open }}</td> + <td>{{ proceedings.submissions_deadline }}</td> + <td>{{ proceedings.submissions_close }}</td> + <td><a class="text-danger" href="{% url 'colleges:fellowship_remove_proceedings' fellowship.id proceedings.id %}">Remove Proceedings</a></td> + </tr> + {% endfor %} + <tr> + <td colspan="6" class="py-3 text-center"><a href="{% url 'colleges:fellowship_add_proceedings' fellowship.id %}">Add Proceedings to Guest Fellowship</a></td> + </tr> + </tbody> + </table> + {% endif %} + + <h3>Pool for this Fellowship</h3> + <table class="table table-hover"> + <thead> + <tr> + <th>Submission</th> + <th colspan="2">Status</th> + </tr> + </thead> + <tbody> + {% for submission in fellowship.pool.all %} + <tr> + <td> + <a href="{{ submission.get_absolute_url }}">{{ submission.arxiv_identifier_w_vn_nr }}, {{ submission.title|truncatechars:50 }}</a> + </td> + <td>{{ submission.get_status_display }}</td> + <td> + {% if submission.editor_in_charge == fellowship.contributor %} + <strong>Fellow is Editor-in-charge</strong> + {% else %} + <a class="text-danger" href="{% url 'colleges:fellowship_remove_submission' fellowship.id submission.arxiv_identifier_w_vn_nr %}">Remove from this Fellowship's pool</a> + {% endif %} + </td> + </tr> + {% endfor %} + <tr> + <td colspan="3" class="py-3 text-center"><a href="{% url 'colleges:fellowship_add_submission' fellowship.id %}">Add Submission to this Fellowship's pool</a></td> + </tr> + </tbody> + </table> + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_edit.html b/colleges/templates/colleges/fellowship_edit.html new file mode 100644 index 0000000000000000000000000000000000000000..809e85b64e27ac0871fff813e2416a90a2bb506d --- /dev/null +++ b/colleges/templates/colleges/fellowship_edit.html @@ -0,0 +1,26 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <a href="{{ fellowship.get_absolute_url }}" class="breadcrumb-item">Fellowship details</a> + <span class="breadcrumb-item">Edit Fellowship</span> +{% endblock %} + +{% block pagetitle %}: Edit Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Edit Fellowship</h1> + <h2 class="text-primary">{{ fellowship }}</h2> + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary" type="submit" value="Save"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_proceedings_add.html b/colleges/templates/colleges/fellowship_proceedings_add.html new file mode 100644 index 0000000000000000000000000000000000000000..391f4bf71fe36acc8ef60cc6f3bde01ac1071001 --- /dev/null +++ b/colleges/templates/colleges/fellowship_proceedings_add.html @@ -0,0 +1,26 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <a href="{{ fellowship.get_absolute_url }}" class="breadcrumb-item">Fellowship details</a> + <span class="breadcrumb-item">Add Proceedings</span> +{% endblock %} + +{% block pagetitle %}: Add Proceedings to Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Add Proceedings to Fellowship</h1> + <h2 class="text-primary">Fellowship {{ fellowship }}</h2> + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary px-3" type="submit" value="Add Submission"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_proceedings_remove.html b/colleges/templates/colleges/fellowship_proceedings_remove.html new file mode 100644 index 0000000000000000000000000000000000000000..84f51f9596766dd7f2cd5fe4a055c3e110acc132 --- /dev/null +++ b/colleges/templates/colleges/fellowship_proceedings_remove.html @@ -0,0 +1,29 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <a href="{{ fellowship.get_absolute_url }}" class="breadcrumb-item">Fellowship details</a> + <span class="breadcrumb-item">Remove Proceedings from Pool</span> +{% endblock %} + +{% block pagetitle %}: Remove Proceedings from Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Remove Proceedings from Pool</h1> + <h2 class="text-primary">Fellowship {{ fellowship }}</h2> + + <h3>Proceedings details</h3> + {% include 'partials/proceedings/summary.html' with proceedings=proceedings %} + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-danger px-3" type="submit" value="Remove from Pool"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_submission_add.html b/colleges/templates/colleges/fellowship_submission_add.html new file mode 100644 index 0000000000000000000000000000000000000000..36c617c158073e29e21012c88938137f9f2c7e55 --- /dev/null +++ b/colleges/templates/colleges/fellowship_submission_add.html @@ -0,0 +1,26 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <a href="{{ fellowship.get_absolute_url }}" class="breadcrumb-item">Fellowship details</a> + <span class="breadcrumb-item">Add Submission to Pool</span> +{% endblock %} + +{% block pagetitle %}: Add Submission to Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Add Submission to Pool</h1> + <h2 class="text-primary">Fellowship {{ fellowship }}</h2> + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary px-3" type="submit" value="Add Submission"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowship_submission_remove.html b/colleges/templates/colleges/fellowship_submission_remove.html new file mode 100644 index 0000000000000000000000000000000000000000..c5defe25aec8a8c6f7f2828fc603dbcecfedfa9b --- /dev/null +++ b/colleges/templates/colleges/fellowship_submission_remove.html @@ -0,0 +1,29 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:fellowships' %}" class="breadcrumb-item">Active Fellowships</a> + <a href="{{ fellowship.get_absolute_url }}" class="breadcrumb-item">Fellowship details</a> + <span class="breadcrumb-item">Remove Submission from Pool</span> +{% endblock %} + +{% block pagetitle %}: Remove Submission from Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Remove Submission from Pool</h1> + <h2 class="text-primary">Fellowship {{ fellowship }}</h2> + + <h3>Submission details</h3> + {% include 'submissions/_submission_summary_short.html' with submission=submission %} + <br> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-danger px-3" type="submit" value="Remove from Pool"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/fellowships.html b/colleges/templates/colleges/fellowships.html new file mode 100644 index 0000000000000000000000000000000000000000..ce1ef2db9cd0fd3269db819a502fa3869ef3d1d2 --- /dev/null +++ b/colleges/templates/colleges/fellowships.html @@ -0,0 +1,74 @@ +{% extends 'submissions/admin/base.html' %} + +{% block breadcrumb_items %} + {{ block.super }} + <span class="breadcrumb-item">Active Fellowships</span> +{% endblock %} + +{% block pagetitle %}: Active Fellowships{% endblock pagetitle %} + +{% block content %} + <h1>Active Regular Fellowships</h1> + <a href="{% url 'colleges:fellowship_add' %}">Add new Fellowship</a> + + <table class="table mt-3"> + <thead> + <tr> + <th>Fellow</th> + <th>Discipline</th> + <th>Start date</th> + <th>End date</th> + <th></th> + </tr> + </thead> + <tbody> + {% for fellow in fellowships.regular %} + <tr> + <td>{{ fellow.contributor }}</td> + <td>{{ fellow.contributor.get_discipline_display }}</td> + <td>{{ fellow.start_date|default:'<i>No start date</i>' }}</td> + <td>{{ fellow.until_date|default:'<i>No end date</i>' }}</td> + <td> + <a href="{{ fellow.get_absolute_url }}">View Fellowship details</a> + </td> + </tr> + {% empty %} + <tr> + <td class="text-danger py-2" colspan="4">There are no active fellowships!</td> + </tr> + {% endfor %} + </tbody> + </table> + + <h1>Active Guest Fellowships</h1> + <a href="{% url 'colleges:fellowship_add' %}?guest=1">Add new Guest Fellowship</a> + + <table class="table mt-3"> + <thead> + <tr> + <th>Fellow</th> + <th>Discipline</th> + <th>Start date</th> + <th>End date</th> + <th></th> + </tr> + </thead> + <tbody> + {% for fellow in fellowships.guests %} + <tr> + <td>{{ fellow.contributor }}</td> + <td>{{ fellow.contributor.get_discipline_display }}</td> + <td>{{ fellow.start_date|default:'<i>No start date</i>' }}</td> + <td>{{ fellow.until_date|default:'<i>No end date</i>' }}</td> + <td> + <a href="{{ fellow.get_absolute_url }}">View Fellowship details</a> + </td> + </tr> + {% empty %} + <tr> + <td class="py-2" colspan="4">There are no active guests fellowships</td> + </tr> + {% endfor %} + </tbody> + </table> +{% endblock %} diff --git a/colleges/templates/colleges/submission_add.html b/colleges/templates/colleges/submission_add.html new file mode 100644 index 0000000000000000000000000000000000000000..e071c00b49bf87ae604544bc030a88a39680d426 --- /dev/null +++ b/colleges/templates/colleges/submission_add.html @@ -0,0 +1,30 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'colleges:submission' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Submission Pool Composition</a> + <span class="breadcrumb-item">Add Fellowship</span> +{% endblock %} + +{% block pagetitle %}: Add Fellowship{% endblock pagetitle %} + +{% block content %} + <h1>Add Fellowship to Submission's Pool</h1> + <h2 class="text-primary">{{submission.title}}</h2> + <h3 class="mb-3">by {{submission.author_list}}</h3> + {% include 'submissions/_submission_summary.html' with submission=submission hide_title=1 %} + <br> + + <h3>Choose one of the following (active) Fellowships to add to the Pool:</h3> + {% include 'partials/colleges/conflicts_of_interests.html' with submission=submission %} + <br> + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary" type="submit" value="Add Fellowship"> + </form> + + +{% endblock %} diff --git a/colleges/templates/colleges/submission_pool.html b/colleges/templates/colleges/submission_pool.html new file mode 100644 index 0000000000000000000000000000000000000000..1b487dc58ba434d0d1b45f38888154d73703447d --- /dev/null +++ b/colleges/templates/colleges/submission_pool.html @@ -0,0 +1,48 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <span class="breadcrumb-item">Submission Pool Composition</span> +{% endblock %} + +{% block pagetitle %}: Submission Pool Composition{% endblock pagetitle %} + +{% block content %} + <h1>Submission Pool Composition</h1> + <h2 class="text-primary">{{submission.title}}</h2> + <h3 class="mb-3">by {{submission.author_list}}</h3> + {% include 'submissions/_submission_summary.html' with submission=submission hide_title=1 %} + <br> + + <h3>Pool Composition</h3> + {% include 'partials/colleges/conflicts_of_interests.html' with submission=submission %} + <table class="table table-hover"> + <thead> + <tr> + <th>Fellowship ID</th> + <th>Fellow</th> + <th>Type</th> + <th colspan="2">Date range</th> + </tr> + </thead> + <tbody> + {% for fellowship in submission.fellows.all %} + <tr> + <td>{{ fellowship.id }}</td> + <td>{{ fellowship.contributor }}</td> + <td>{{ fellowship.guest|yesno:"Guest fellowship,Regular fellowship"|safe }}</td> + <td> + <a class="text-danger" href="{% url 'colleges:fellowship_remove_submission' fellowship.id submission.arxiv_identifier_w_vn_nr %}">Remove this Fellowship from Submission's pool</a> + </td> + </tr> + {% endfor %} + <tr> + <td colspan="4" class="py-3 text-center"><a href="{% url 'colleges:submission_add_fellowship' submission.arxiv_identifier_w_vn_nr %}">Add Fellowship to this Submission's pool</a></td> + </tr> + </tbody> + </table> + + +{% endblock %} diff --git a/colleges/templates/partials/colleges/conflicts_of_interests.html b/colleges/templates/partials/colleges/conflicts_of_interests.html new file mode 100644 index 0000000000000000000000000000000000000000..6ad78a9774a6bd11809199f0f337b4a2c272645b --- /dev/null +++ b/colleges/templates/partials/colleges/conflicts_of_interests.html @@ -0,0 +1,5 @@ +{% comment %} + + Pretty damn complicated + +{% endcomment %} diff --git a/colleges/tests.py b/colleges/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/colleges/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/colleges/urls.py b/colleges/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..e5ddb94593e636403f50668cb851337abfa3e211 --- /dev/null +++ b/colleges/urls.py @@ -0,0 +1,31 @@ +from django.conf.urls import url + +from submissions.constants import SUBMISSIONS_COMPLETE_REGEX + +from . import views + +urlpatterns = [ + # Fellowships + url(r'^fellowships/$', views.fellowships, name='fellowships'), + url(r'^fellowships/add$', views.fellowship_add, name='fellowship_add'), + url(r'^fellowships/(?P<id>[0-9]+)/$', views.fellowship_detail, name='fellowship'), + url(r'^fellowships/(?P<id>[0-9]+)/edit$', views.fellowship_edit, name='fellowship_edit'), + url(r'^fellowships/(?P<id>[0-9]+)/terminate$', views.fellowship_terminate, + name='fellowship_terminate'), + url(r'^fellowships/submissions/{regex}/$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.submission_pool, + name='submission'), + url(r'^fellowships/submissions/{regex}/add$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.submission_add_fellowship, + name='submission_add_fellowship'), + url(r'^fellowships/(?P<id>[0-9]+)/submissions/{regex}/remove$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.fellowship_remove_submission, + name='fellowship_remove_submission'), + url(r'^fellowships/(?P<id>[0-9]+)/submissions/add$', + views.fellowship_add_submission, name='fellowship_add_submission'), + + url(r'^fellowships/(?P<id>[0-9]+)/proceedings/add$', + views.fellowship_add_proceedings, name='fellowship_add_proceedings'), + url(r'^fellowships/(?P<id>[0-9]+)/proceedings/(?P<proceedings_id>[0-9]+)/remove$', + views.fellowship_remove_proceedings, name='fellowship_remove_proceedings'), +] diff --git a/colleges/views.py b/colleges/views.py new file mode 100644 index 0000000000000000000000000000000000000000..81bc5f917f3c16d522aedcd778f2fedfd4bee4d2 --- /dev/null +++ b/colleges/views.py @@ -0,0 +1,229 @@ +from django.contrib import messages +from django.contrib.auth.decorators import login_required, permission_required +from django.shortcuts import get_object_or_404, render, redirect +from django.core.urlresolvers import reverse + +from proceedings.models import Proceedings +from submissions.models import Submission + +from .forms import FellowshipForm, FellowshipTerminateForm, FellowshipRemoveSubmissionForm,\ + FellowshipAddSubmissionForm, AddFellowshipForm, SubmissionAddFellowshipForm,\ + FellowshipRemoveProceedingsForm, FellowshipAddProceedingsForm +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. + """ + fellowships = Fellowship.objects.active() + + context = { + 'fellowships': fellowships + } + return render(request, 'colleges/fellowships.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_detail(request, id): + """ + View details of a specific fellowship + """ + fellowship = get_object_or_404(Fellowship, id=id) + + context = { + 'fellowship': fellowship + } + return render(request, 'colleges/fellowship_details.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_add(request): + """ + Create a new Fellowship. + """ + form = AddFellowshipForm(request.POST or None, initial=request.GET or None) + + if form.is_valid(): + fellowship = form.save() + messages.success(request, 'Fellowship added.') + return redirect(fellowship.get_absolute_url()) + + context = { + 'form': form + } + return render(request, 'colleges/fellowship_add.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_edit(request, id): + """ + Edit basic information about fellowship. + """ + fellowship = get_object_or_404(Fellowship, id=id) + form = FellowshipForm(request.POST or None, instance=fellowship) + + if form.is_valid(): + form.save() + messages.success(request, 'Fellowship updated.') + return redirect(fellowship.get_absolute_url()) + + context = { + 'fellowship': fellowship, + 'form': form + } + return render(request, 'colleges/fellowship_edit.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_terminate(request, id): + """ + Terminate Fellowship by setting the until_date to today's date. + """ + fellowship = get_object_or_404(Fellowship, id=id) + form = FellowshipTerminateForm(request.POST or None, instance=fellowship) + + if form.is_valid(): + form.save() + messages.success(request, 'Fellowship terminated.') + else: + messages.warning(request, 'Fellowship has not been terminated, please try again.') + return redirect(fellowship.get_absolute_url()) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def submission_pool(request, arxiv_identifier_w_vn_nr): + """ + List all Fellowships related to Submission. + """ + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + + context = { + 'submission': submission + } + return render(request, 'colleges/submission_pool.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def submission_add_fellowship(request, arxiv_identifier_w_vn_nr): + """ + Add Fellowship to the pool of a Submission. + """ + submission = get_object_or_404(Submission, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + form = SubmissionAddFellowshipForm(request.POST or None, instance=submission) + + if form.is_valid(): + form.save() + messages.success(request, 'Fellowship {fellowship} ({id}) added to Submission.'.format( + fellowship=form.cleaned_data['fellowship'].contributor, + id=form.cleaned_data['fellowship'].id)) + return redirect(reverse('colleges:submission', + args=(submission.arxiv_identifier_w_vn_nr,))) + + context = { + 'submission': submission, + 'form': form, + } + return render(request, 'colleges/submission_add.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_remove_submission(request, id, arxiv_identifier_w_vn_nr): + """ + Remove Submission from the pool of a Fellowship. + """ + fellowship = get_object_or_404(Fellowship, id=id) + submission = get_object_or_404(fellowship.pool.all(), + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + form = FellowshipRemoveSubmissionForm(request.POST or None, + submission=submission, instance=fellowship) + + if form.is_valid() and request.POST: + form.save() + messages.success(request, 'Submission {sub} removed from Fellowship.'.format( + sub=arxiv_identifier_w_vn_nr)) + return redirect(fellowship.get_absolute_url()) + + context = { + 'fellowship': fellowship, + 'form': form, + 'submission': submission + } + return render(request, 'colleges/fellowship_submission_remove.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_add_submission(request, id): + """ + Add Submission to the pool of a Fellowship. + """ + fellowship = get_object_or_404(Fellowship, id=id) + form = FellowshipAddSubmissionForm(request.POST or None, instance=fellowship) + + if form.is_valid(): + form.save() + messages.success(request, 'Submission {submission} added to Fellowship.'.format( + submission=form.cleaned_data['submission'].arxiv_identifier_w_vn_nr)) + return redirect(fellowship.get_absolute_url()) + + context = { + 'fellowship': fellowship, + 'form': form, + } + return render(request, 'colleges/fellowship_submission_add.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_remove_proceedings(request, id, proceedings_id): + """ + Remove Proceedings from the pool of a Fellowship. + """ + fellowship = get_object_or_404(Fellowship, id=id) + proceedings = get_object_or_404(fellowship.proceedings.all(), id=proceedings_id) + form = FellowshipRemoveProceedingsForm(request.POST or None, + proceedings=proceedings, instance=fellowship) + + if form.is_valid() and request.POST: + form.save() + messages.success(request, 'Proceedings %s removed from Fellowship.' % str(proceedings)) + return redirect(fellowship.get_absolute_url()) + + context = { + 'fellowship': fellowship, + 'form': form, + 'proceedings': proceedings + } + return render(request, 'colleges/fellowship_proceedings_remove.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def fellowship_add_proceedings(request, id): + """ + Add Proceedings to the pool of a Fellowship. + """ + fellowship = get_object_or_404(Fellowship, id=id) + form = FellowshipAddProceedingsForm(request.POST or None, instance=fellowship) + + if form.is_valid(): + form.save() + proceedings = form.cleaned_data.get('proceedings', '') + messages.success(request, 'Proceedings %s added to Fellowship.' % str(proceedings)) + return redirect(fellowship.get_absolute_url()) + + context = { + 'fellowship': fellowship, + 'form': form, + } + return render(request, 'colleges/fellowship_proceedings_add.html', context) diff --git a/commentaries/templates/commentaries/commentary_list.html b/commentaries/templates/commentaries/commentary_list.html index 40efb8b4b21db67137944de2ca4905e42c818b2e..37a6123d03b8432b7871102fcc4f4ba4f70eaa91 100644 --- a/commentaries/templates/commentaries/commentary_list.html +++ b/commentaries/templates/commentaries/commentary_list.html @@ -71,33 +71,28 @@ {% else %} <h2>Search results:</h3> {% endif %} - {% if commentary_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for object in commentary_list %} - <li class="list-group-item"> - {% include 'commentaries/_commentary_card_content.html' with commentary=object %} - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for object in commentary_list %} + <li class="list-group-item"> + {% include 'commentaries/_commentary_card_content.html' with commentary=object %} + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/commentaries/templates/commentaries/vet_commentary_requests.html b/commentaries/templates/commentaries/vet_commentary_requests.html index e6c77048113d89bf60598f70b270c15e25022a67..054c8bf06782c6dc32128bace37b2e33a6ffc176 100644 --- a/commentaries/templates/commentaries/vet_commentary_requests.html +++ b/commentaries/templates/commentaries/vet_commentary_requests.html @@ -11,31 +11,27 @@ {% block content %} -<div class="row"> - <div class="col-12"> - {% if not commentary_to_vet %} - <h1>There are no Commentary Page requests for you to vet.</h1> - <h3><a href="{% url 'scipost:personal_page' %}">Return to personal page</a></h3> - {% else %} - <h1>SciPost Commentary Page request to vet:</h1> - - <hr> - <div class="row"> - <div class="col-md-7"> - {% include 'commentaries/_commentary_summary.html' with commentary=commentary_to_vet %} - <h3 class="mt-4">Abstract:</h3> - <p>{{ commentary_to_vet.pub_abstract }}</p> - - </div> - <div class="col-md-5"> - <form action="{% url 'commentaries:vet_commentary_requests_submit' commentary_id=commentary_to_vet.id %}" method="post"> - {% csrf_token %} - {{ form|bootstrap }} - <input type="submit" class="btn btn-secondary" value="Submit" /> - </div> - </div> - {% endif %} +{% if not commentary_to_vet %} + <h1>There are no Commentary Page requests for you to vet.</h1> + <h3><a href="{% url 'scipost:personal_page' %}">Return to personal page</a></h3> +{% else %} + <h1 class="highlight">SciPost Commentary Page request to vet:</h1> + + + <div class="card"> + <div class="card-body"> + {% include 'commentaries/_commentary_summary.html' with commentary=commentary_to_vet %} + <h3 class="mt-4">Abstract:</h3> + <p>{{ commentary_to_vet.pub_abstract }}</p> + + </div> + <div class="card-body"> + <form action="{% url 'commentaries:vet_commentary_requests_submit' commentary_id=commentary_to_vet.id %}" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input type="submit" class="btn btn-primary" value="Submit" /> </div> -</div> + </div> +{% endif %} {% endblock %} diff --git a/commentaries/views.py b/commentaries/views.py index dcbf31f3ff6c8fc1a92becea8812706c7e13e541..dd60ecd04fe4c11fe0b4be93ae4f4db60f8d9a6b 100644 --- a/commentaries/views.py +++ b/commentaries/views.py @@ -16,6 +16,7 @@ from .forms import DOIToQueryForm, ArxivQueryForm, VetCommentaryForm, RequestCom from comments.models import Comment from comments.forms import CommentForm +from scipost.mixins import PaginationMixin import strings @@ -190,7 +191,7 @@ def modify_commentary_request(request, commentary_id): return render(request, 'commentaries/modify_commentary_request.html', context) -class CommentaryListView(ListView): +class CommentaryListView(PaginationMixin, ListView): model = Commentary form = CommentarySearchForm paginate_by = 10 diff --git a/comments/templates/comments/vet_submitted_comments.html b/comments/templates/comments/vet_submitted_comments.html index 1854a83999f2c64849f4791ee3840077fa8c6e57..e53caae093879d9c9f61ab201d86ba90e82eed2f 100644 --- a/comments/templates/comments/vet_submitted_comments.html +++ b/comments/templates/comments/vet_submitted_comments.html @@ -14,83 +14,20 @@ {% block content %} {% if not comments_to_vet %} -<div class="row"> - <div class="col-12"> - <h1>There are no comments for you to vet.</h1> - <h3><a href="{% url 'scipost:personal_page' %}">Return to personal page</a></h3> + <div class="row"> + <div class="col-12"> + <h1>There are no comments for you to vet.</h1> + <h3><a href="{% url 'scipost:personal_page' %}">Return to personal page</a></h3> + </div> </div> -</div> {% else %} -<div class="row"> - <div class="col-12"> - <h1 class="highlight">SciPost Comments to vet:</h1> - </div> -</div> - -<div class="row"> - <div class="col-12"> - {% for comment_to_vet in comments_to_vet %} - <div class="card card-vetting"> - <div class="card-header"> - - {% if comment_to_vet.commentary %} - <h2>From Commentary (<a href="{% url 'commentaries:commentary' arxiv_or_DOI_string=comment_to_vet.commentary.arxiv_or_DOI_string %}">link</a>)</h2> - {% include 'commentaries/_commentary_summary.html' with commentary=comment_to_vet.commentary %} - {% endif %} - - {% if comment_to_vet.submission %} - <h2>From Submission (<a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=comment_to_vet.submission.arxiv_identifier_w_vn_nr %}">link</a>)</h2> - {% include 'submissions/_submission_summary_short.html' with submission=comment_to_vet.submission %} - {% endif %} - {% if comment_to_vet.thesislink %} - <h2>From Thesis Link (<a href="{% url 'theses:thesis' comment_to_vet.thesislink.id %}">link</a>)</h2> - {% include 'theses/_thesislink_information.html' with thesislink=comment_to_vet.thesislink %} - {% endif %} - </div> - <div class="card-body"> + <h1 class="highlight">SciPost Comments to vet:</h1> - <h2 class="card-title">The Comment to be vetted:</h2> + {% for comment_to_vet in comments_to_vet %} + {% include 'comments/_vet_comment_form.html' with comment=comment_to_vet form=form %} + {% endfor %} - <div class="row"> - <div class="col-md-6"> - {% include 'comments/_comment_identifier_vetting.html' with comment=comment_to_vet %} - <hr class="small"> - - <h3>Comment text:</h3> - <p>{{ comment_to_vet.comment_text }}</p> - - {% if comment_to_vet.file_attachment %} - <h3>Attachment:</h3> - <p> - <a target="_blank" href="{{ comment_to_vet.file_attachment.url }}"> - {% if comment_to_vet.file_attachment|is_image %} - <img class="attachment attachment-comment" src="{{ comment_to_vet.file_attachment.url }}"> - {% else %} - {{ comment_to_vet.file_attachment|filename }}<br><small>{{ comment_to_vet.file_attachment.size|filesizeformat }}</small> - {% endif %} - </a> - </p> - {% endif %} - - {% if comment_to_vet.remarks_for_editors %} - <h3>Remarks for Editors only:</h3> - <p>{{ comment_to_vet.remarks_for_editors }}</p> - {% endif %} - </div> - <div class="col-md-6"> - <form action="{% url 'comments:vet_submitted_comment_ack' comment_id=comment_to_vet.id %}" method="post"> - {% csrf_token %} - {{ form|bootstrap }} - <input class="btn btn-primary" type="submit" value="Submit" /> - </form> - </div> - </div> - </div> - </div> - {% endfor %} - </div> -</div> {% endif %} {% endblock content %} diff --git a/comments/templates/comments/vet_submitted_comments_list.html b/comments/templates/comments/vet_submitted_comments_list.html deleted file mode 100644 index d58676554085260383dffe0c957a9578d7821357..0000000000000000000000000000000000000000 --- a/comments/templates/comments/vet_submitted_comments_list.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends 'scipost/base.html' %} - -{% block pagetitle %}: vet comments{% endblock pagetitle %} - -{% block content %} - -{% if not comments_to_vet %} -<div class="row"> - <div class="col-12"> - <h1 class="highlight">There are no comments for you to vet.</h1> - </div> -</div> -{% else %} -<div class="row"> - <div class="col-12"> - <h1 class="highlight">SciPost Comments to vet:</h1> - </div> -</div> - -<div class="row"> - <div class="col-12"> - {% for comment_to_vet in comments_to_vet %} - {% include 'comments/_vet_comment_form.html' with comment=comment_to_vet form=form %} - {% endfor %} - </div> -</div> -{% endif %} - -{% endblock content %} diff --git a/comments/views.py b/comments/views.py index e4c909d39fca62cefd2dd7360672ce3291a789f8..97ec52a69e630c34b349003b46ea59048fb84afe 100644 --- a/comments/views.py +++ b/comments/views.py @@ -53,7 +53,7 @@ def vet_submitted_comments_list(request): comments_to_vet = Comment.objects.awaiting_vetting().order_by('date_submitted') form = VetCommentForm() context = {'comments_to_vet': comments_to_vet, 'form': form} - return(render(request, 'comments/vet_submitted_comments_list.html', context)) + return(render(request, 'comments/vet_submitted_comments.html', context)) @login_required diff --git a/cronjob_production.sh b/cronjob_production.sh new file mode 100644 index 0000000000000000000000000000000000000000..645a7b10bfa68bb34363053f06cfe09634a47839 --- /dev/null +++ b/cronjob_production.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +cd /home/jscaux/webapps/scipost/SciPost_v1/ +export DJANGO_SETTINGS_MODULE='SciPost_v1.settings.production' + +/usr/local/bin/python3.5 manage.py remind_fellows_to_submit_report diff --git a/cronjob_staging.sh b/cronjob_staging.sh new file mode 100644 index 0000000000000000000000000000000000000000..98bfc21a2764d8c2803e8b0738b20b880b5f18af --- /dev/null +++ b/cronjob_staging.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +cd /home/jdewit/webapps/scipost/SciPost_v1/ +export DJANGO_SETTINGS_MODULE='SciPost_v1.settings.staging_release' + +/usr/local/bin/python3.5 manage.py remind_fellows_to_submit_report diff --git a/finances/templates/finances/worklog_confirm_delete.html b/finances/templates/finances/worklog_confirm_delete.html index cc03bcc7db216d340cdee18bff64e842a149e612..9b6200d7c1a022dbb8d7f9247cfcecff803eba0a 100644 --- a/finances/templates/finances/worklog_confirm_delete.html +++ b/finances/templates/finances/worklog_confirm_delete.html @@ -14,7 +14,7 @@ <div class="row"> <div class="col-12"> <h1 class="highlight">Delete log</h1> - {% include 'submissions/_submission_card_content_sparse.html' with submission=object.content.submission %} + {% include 'partials/submissions/submission_card_content.html' with submission=object.content.submission %} </div> </div> <div class="row"> diff --git a/journals/constants.py b/journals/constants.py index 7673cf16062813b0d1ceba90839c40b082fce962..3c1d7b5b173d7d7468dc6758ab0621abbb99ea34 100644 --- a/journals/constants.py +++ b/journals/constants.py @@ -7,7 +7,8 @@ SCIPOST_JOURNAL_PHYSICS_PROC = 'SciPostPhysProc' # Journal open for submission SCIPOST_JOURNALS_SUBMIT = ( (SCIPOST_JOURNAL_PHYSICS, 'SciPost Physics'), - (SCIPOST_JOURNAL_PHYSICS_LECTURE_NOTES, 'SciPost Physics Lecture Notes') + (SCIPOST_JOURNAL_PHYSICS_LECTURE_NOTES, 'SciPost Physics Lecture Notes'), + (SCIPOST_JOURNAL_PHYSICS_PROC, 'SciPost Proceedings') ) # Journal closed for submission diff --git a/journals/forms.py b/journals/forms.py index 688ade7e6c2f450da0473aeadc48cabb756c1dff..3883c6af3ad372e3489770a8ea5b00f3cfe6e822 100644 --- a/journals/forms.py +++ b/journals/forms.py @@ -11,7 +11,7 @@ from submissions.models import Submission class InitiatePublicationForm(forms.Form): accepted_submission = forms.ModelChoiceField(queryset=Submission.objects.accepted()) to_be_issued_in = forms.ModelChoiceField( - queryset=Issue.objects.filter(until_date__gt=timezone.now())) + queryset=Issue.objects.filter(until_date__gte=timezone.now())) def __init__(self, *args, **kwargs): super(InitiatePublicationForm, self).__init__(*args, **kwargs) diff --git a/journals/migrations/0046_auto_20171019_1942.py b/journals/migrations/0046_auto_20171019_1942.py new file mode 100644 index 0000000000000000000000000000000000000000..1c199f6062ca8483423a788fdcfee6aa3fbc523d --- /dev/null +++ b/journals/migrations/0046_auto_20171019_1942.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-19 17:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('journals', '0045_auto_20170925_2124'), + ] + + operations = [ + migrations.AlterField( + model_name='journal', + name='name', + field=models.CharField(choices=[('SciPostPhys', 'SciPost Physics'), ('SciPostPhysLectNotes', 'SciPost Physics Lecture Notes'), ('SciPostPhysProc', 'SciPost Proceedings'), ('SciPostPhysSel', 'SciPost Physics Select'), ('SciPostPhysProc', 'SciPost Physics Proceedings')], max_length=100, unique=True), + ), + ] diff --git a/journals/templates/journals/_publication_details.html b/journals/templates/journals/_publication_details.html index a8844ec1995f4804de33d1e8d72f772635353a11..014da1f23f015d0a82d9b59bf0be546a35470a09 100644 --- a/journals/templates/journals/_publication_details.html +++ b/journals/templates/journals/_publication_details.html @@ -4,14 +4,14 @@ <h2 class="pb-1 text-blue">{{publication.title}}</h2> <p class="mb-1">{{ publication.author_list }}</p> - <p class="text-muted"> + <p class="text-muted mb-0"> {{ publication.citation }} · published {{ publication.publication_date|date:'j F Y' }} {% if publication.cc_license != 'CC BY 4.0' %} · licensed under {{publication.get_cc_license_display}} {% endif %} </p> - <ul class="publicationClickables"> + <ul class="publicationClickables mt-3"> <li>doi: {{publication.doi_string}}</li> <li class="publicationPDF"> <a href="{{publication.get_absolute_url}}/pdf" target="_blank">pdf</a> @@ -29,6 +29,11 @@ </div> <div class="row"> <div class="col-12"> + {% if publication.in_issue.proceedings %} + <h3>Proceedings event</h3> + <p><a href="{{ publication.in_issue.get_absolute_url }}">{{ publication.in_issue.proceedings.event_name }}</a></p> + {% endif %} + <h3>Abstract</h3> <p class="abstract">{{ publication.abstract }}</p> </div> diff --git a/journals/templates/journals/journal_accepted.html b/journals/templates/journals/journal_accepted.html index 7b1b7a0b0b9efb37beb87dcade9a80cef23a6109..2eb16483da99aa3932b753af4b69e555a40c39af 100644 --- a/journals/templates/journals/journal_accepted.html +++ b/journals/templates/journals/journal_accepted.html @@ -21,7 +21,9 @@ <ul class="list-group list-group-flush"> {% for submission in accepted_SP_submissions %} <li class="list-group-item"> - {% include 'submissions/_submission_card_content.html' with submission=submission %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=submission %} + </div> </li> {% empty %} <li class="list-group-item"> diff --git a/journals/templates/journals/journal_issue_detail.html b/journals/templates/journals/journal_issue_detail.html index c15afdb79d285325108d0deea87cec3ed6452ca5..6b646613d4d4de29b67a170ad2c1d32a6e20dbf2 100644 --- a/journals/templates/journals/journal_issue_detail.html +++ b/journals/templates/journals/journal_issue_detail.html @@ -27,6 +27,10 @@ {{block.super}} {% endwith %} + {% if issue.proceedings %} + {% include 'partials/proceedings/description.html' with proceedings=issue.proceedings %} + {% endif %} + <div class="row"> <div class="col-12"> <ul class="list-unstyled"> diff --git a/journals/views.py b/journals/views.py index 160cee4591d95f60e4eb99ae58df0604dab09bfa..792062e6b868e99ac9f1f681f05f768a39ded83f 100644 --- a/journals/views.py +++ b/journals/views.py @@ -245,7 +245,6 @@ def validate_publication(request): publication = validate_publication_form.save() # Fill in remaining data - #publication.pdf_file = request.FILES['pdf_file'] submission = publication.accepted_submission publication.authors.add(*submission.authors.all()) if publication.first_author: diff --git a/notifications/admin.py b/notifications/admin.py index 2cf8c7c7b329a7a98b23bb5332d71059d5023d56..247e0620f5986d20ab061e97750e1053eb4ca53a 100644 --- a/notifications/admin.py +++ b/notifications/admin.py @@ -5,8 +5,8 @@ from .models import Notification class NotificationAdmin(admin.ModelAdmin): raw_id_fields = ('recipient', ) list_display = ('recipient', 'actor', - 'level', 'target', 'unread', 'public') - list_filter = ('level', 'unread', 'public', 'created', ) + 'level', 'target', 'unread',) + list_filter = ('level', 'unread', 'created',) admin.site.register(Notification, NotificationAdmin) diff --git a/notifications/constants.py b/notifications/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..d160034357dfbda4f17bda8cb90a1eab3f2b34ae --- /dev/null +++ b/notifications/constants.py @@ -0,0 +1,7 @@ +NOTIFICATION_REFEREE_DEADLINE = 'referee_task_deadline' +NOTIFICATION_REFEREE_OVERDUE = 'referee_task_overdue' + +NOTIFICATION_TYPES = ( + (NOTIFICATION_REFEREE_DEADLINE, 'Refereeing Task is approaching its deadline'), + (NOTIFICATION_REFEREE_OVERDUE, 'Refereeing Task is overdue') +) diff --git a/notifications/migrations/0002_auto_20171021_1821.py b/notifications/migrations/0002_auto_20171021_1821.py new file mode 100644 index 0000000000000000000000000000000000000000..30945c04698db4acdb74c2157fc7a2c76e372d3a --- /dev/null +++ b/notifications/migrations/0002_auto_20171021_1821.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-21 16:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('notifications', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='notification', + name='emailed', + ), + migrations.RemoveField( + model_name='notification', + name='public', + ), + migrations.AddField( + model_name='notification', + name='internal_type', + field=models.CharField(blank=True, choices=[('referee_task_deadline', 'Refereeing Task is approaching its deadline'), ('referee_task_overdue', 'Refereeing Task is overdue')], max_length=255), + ), + ] diff --git a/notifications/models.py b/notifications/models.py index ecec80cfea09c80841445b49b984d9b8cde60c25..d7d9fef894b28bc7af060517cb9d136c502f0940 100644 --- a/notifications/models.py +++ b/notifications/models.py @@ -5,6 +5,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from django.utils import timezone +from .constants import NOTIFICATION_TYPES from .managers import NotificationQuerySet @@ -52,8 +53,9 @@ class Notification(models.Model): created = models.DateTimeField(default=timezone.now) - public = models.BooleanField(default=True) - emailed = models.BooleanField(default=False) + # This field is for internal use only. It is used to prevent duplicate sending + # of notifications. + internal_type = models.CharField(max_length=255, blank=True, choices=NOTIFICATION_TYPES) objects = NotificationQuerySet.as_manager() diff --git a/notifications/signals.py b/notifications/signals.py index af8be2f2807ae3a16573f49e4319d49b5a615dac..94355790559049e14241f89fb8c4cddd8d65f779 100644 --- a/notifications/signals.py +++ b/notifications/signals.py @@ -4,7 +4,7 @@ from .models import Notification notify = Signal(providing_args=[ - 'recipient', 'actor', 'verb', 'action_object', 'target', 'description', 'level' + 'recipient', 'actor', 'verb', 'action_object', 'target', 'description', 'level', 'type' ]) @@ -23,7 +23,8 @@ def notify_receiver(sender, **kwargs): action_object=kwargs.get('action_object'), target=kwargs.get('target'), description=kwargs.get('description'), - level=kwargs.get('level', 'info') + level=kwargs.get('level', 'info'), + internal_type=kwargs.get('type', '') ) notification.save() print("Request finished!") diff --git a/notifications/templates/notifications/partials/notice.html b/notifications/templates/notifications/partials/notice.html index 5ce4c87d0a529b780c99a5cb9a5113a1cb5497c2..d9ee3bf07a29e07d1dd189665d865c6157ad5dc2 100644 --- a/notifications/templates/notifications/partials/notice.html +++ b/notifications/templates/notifications/partials/notice.html @@ -14,7 +14,7 @@ {% if notice.actor.first_name and notice.actor.last_name %} {{ notice.actor.first_name}} {{ notice.actor.last_name }} {% else %} - {{ notice.actor }} + {# {{ notice.actor }}#} {% endif %} </strong> {{ notice.verb }} diff --git a/notifications/urls.py b/notifications/urls.py index 23bb20e9e1e4aedb2bc6ec2191bf9dbf2f4c5101..7fd8627126d17a50579d3d39bdd523c1841ab137 100644 --- a/notifications/urls.py +++ b/notifications/urls.py @@ -4,7 +4,6 @@ from . import views urlpatterns = [ - url(r'^$', views.AllNotificationsList.as_view(), name='all'), url(r'^redirect/(?P<slug>\d+)$', views.forward, name='forward'), url(r'^mark-all-as-read/$', views.mark_all_as_read, name='mark_all_as_read'), url(r'^mark-toggle/(?P<slug>\d+)/$', views.mark_toggle, name='mark_toggle'), diff --git a/notifications/views.py b/notifications/views.py index e309196bb51f93c2f465baad3b931219655118d6..bcdf7e3b03fc93946b0d254b3136d9c9b342fc5a 100644 --- a/notifications/views.py +++ b/notifications/views.py @@ -3,8 +3,6 @@ from django.contrib.auth.models import User from django.forms import model_to_dict from django.http import JsonResponse from django.shortcuts import get_object_or_404, redirect -from django.utils.decorators import method_decorator -from django.views.generic import ListView from .models import Notification from .utils import id2slug, slug2id @@ -14,20 +12,6 @@ def is_test_user(user): return user.groups.filter(name='Testers').exists() -@method_decorator(login_required, name='dispatch') -@method_decorator(user_passes_test(is_test_user), name='dispatch') -class NotificationViewList(ListView): - context_object_name = 'notifications' - - -class AllNotificationsList(NotificationViewList): - """ - Index page for authenticated user - """ - def get_queryset(self): - return self.request.user.notifications.all() - - @login_required @user_passes_test(is_test_user) def forward(request, slug): @@ -125,7 +109,10 @@ def live_notification_list(request): else: struct['actor'] = str(n.actor) if n.target: - struct['target'] = str(n.target) + if hasattr(n.target, 'notification_name'): + struct['target'] = n.target.notification_name + else: + struct['target'] = str(n.target) struct['forward_link'] = n.get_absolute_url() if n.action_object: struct['action_object'] = str(n.action_object) diff --git a/proceedings/__init__.py b/proceedings/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/proceedings/admin.py b/proceedings/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..67d87120b6087ac7fe9e8825899d9311b5c0e8ed --- /dev/null +++ b/proceedings/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin + +from .models import Proceedings + + +class ProceedingsAdmin(admin.ModelAdmin): + list_display = ('__str__', 'issue',) + list_filter = ('issue',) + + +admin.site.register(Proceedings, ProceedingsAdmin) diff --git a/proceedings/apps.py b/proceedings/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..dd2aa26255e92b46cce1f14e6677000b9f6023e7 --- /dev/null +++ b/proceedings/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ProceedingsConfig(AppConfig): + name = 'proceedings' diff --git a/proceedings/forms.py b/proceedings/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..bd8be93f0fc8c85e6fe364db1c978d2ea4da9c4b --- /dev/null +++ b/proceedings/forms.py @@ -0,0 +1,18 @@ +from django import forms + +from .models import Proceedings + + +class ProceedingsForm(forms.ModelForm): + class Meta: + model = Proceedings + fields = ( + 'issue', + 'event_name', + 'event_description', + 'event_start_date', + 'event_end_date', + 'submissions_open', + 'submissions_deadline', + 'submissions_close', + ) diff --git a/proceedings/managers.py b/proceedings/managers.py new file mode 100644 index 0000000000000000000000000000000000000000..d16a9b116b482a057840e22b2a2b0397edfee902 --- /dev/null +++ b/proceedings/managers.py @@ -0,0 +1,9 @@ +import datetime + +from django.db import models + + +class ProceedingsQuerySet(models.QuerySet): + def open_for_submission(self): + today = datetime.date.today() + return self.filter(submissions_open__lte=today, submissions_close__gte=today) diff --git a/proceedings/migrations/0001_initial.py b/proceedings/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..32cf6e68fd089eec86c74ede3ae26c4761caaa98 --- /dev/null +++ b/proceedings/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-20 07:00 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import scipost.db.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('colleges', '0001_initial'), + ('journals', '0046_auto_20171019_1942'), + ] + + operations = [ + migrations.CreateModel( + name='Proceedings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('latest_activity', scipost.db.fields.AutoDateTimeField(blank=True, default=django.utils.timezone.now, editable=False)), + ('issue_name', models.CharField(max_length=256)), + ('event_name', models.CharField(blank=True, max_length=256)), + ('event_description', models.TextField(blank=True)), + ('event_start_date', models.DateField(blank=True, null=True)), + ('event_end_date', models.DateField(blank=True, null=True)), + ('submissions_open', models.DateField()), + ('submissions_deadline', models.DateField()), + ('submissions_close', models.DateField()), + ('fellowships', models.ManyToManyField(blank=True, related_name='proceedings', to='colleges.Fellowship')), + ('issue', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='proceedings', to='journals.Issue')), + ('lead_fellow', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='colleges.Fellowship')), + ], + options={ + 'verbose_name': 'Proceedings', + 'verbose_name_plural': 'Proceedings', + 'default_related_name': 'proceedings', + }, + ), + ] diff --git a/proceedings/migrations/0002_remove_proceedings_issue_name.py b/proceedings/migrations/0002_remove_proceedings_issue_name.py new file mode 100644 index 0000000000000000000000000000000000000000..0045b112d3a41eec21b759ac43ec1ae0f049070f --- /dev/null +++ b/proceedings/migrations/0002_remove_proceedings_issue_name.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-21 12:56 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('proceedings', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='proceedings', + name='issue_name', + ), + ] diff --git a/proceedings/migrations/__init__.py b/proceedings/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/proceedings/models.py b/proceedings/models.py new file mode 100644 index 0000000000000000000000000000000000000000..83408cac946556362879ca29e7787118a50c2e6b --- /dev/null +++ b/proceedings/models.py @@ -0,0 +1,52 @@ +import datetime + +from django.core.urlresolvers import reverse +from django.db import models + +from scipost.behaviors import TimeStampedModel + +from .managers import ProceedingsQuerySet + + +class Proceedings(TimeStampedModel): + """ + A Proceeding is a special kind of Journal Issue. + """ + # Link to the actual Journal platform + issue = models.OneToOneField('journals.Issue', related_name='proceedings', + limit_choices_to={ + 'in_volume__in_journal__name': 'SciPostPhysProc'}) + + # Event the Proceedings is for + event_name = models.CharField(max_length=256, blank=True) + event_description = models.TextField(blank=True) + event_start_date = models.DateField(null=True, blank=True) + event_end_date = models.DateField(null=True, blank=True) + + # Fellows + lead_fellow = models.ForeignKey('colleges.Fellowship', null=True, blank=True, related_name='+') + fellowships = models.ManyToManyField('colleges.Fellowship', blank=True, + limit_choices_to={'guest': True}) + + # Submission data + submissions_open = models.DateField() + submissions_deadline = models.DateField() + submissions_close = models.DateField() + + objects = ProceedingsQuerySet.as_manager() + + class Meta: + verbose_name = 'Proceedings' + verbose_name_plural = 'Proceedings' + default_related_name = 'proceedings' + + def __str__(self): + return self.event_name + + def get_absolute_url(self): + return reverse('proceedings:proceedings_details', args=(self.id,)) + + @property + def open_for_submission(self): + today = datetime.date.today() + return self.submissions_open <= today and self.submissions_close >= today diff --git a/proceedings/templates/partials/proceedings/description.html b/proceedings/templates/partials/proceedings/description.html new file mode 100644 index 0000000000000000000000000000000000000000..038474ca7039369f707797110c2384a04a68e803 --- /dev/null +++ b/proceedings/templates/partials/proceedings/description.html @@ -0,0 +1,3 @@ +<h3>Event: {{ proceedings.event_name }}</h3> +<h4 class="pt-0 text-muted">From {{ proceedings.event_start_date }} until {{ proceedings.event_end_date }}</h4> +<p class="mt-1">{{ proceedings.event_description|linebreaksbr }}</p> diff --git a/proceedings/templates/partials/proceedings/summary.html b/proceedings/templates/partials/proceedings/summary.html new file mode 100644 index 0000000000000000000000000000000000000000..b7b2e7e513de253e68314826a955d30752d14e04 --- /dev/null +++ b/proceedings/templates/partials/proceedings/summary.html @@ -0,0 +1,42 @@ +<table class="proceedings summary"> + <tr> + <th>Event name</th> + <td>{{ proceedings.event_name }}</td> + </tr> + <tr> + <th>Description</th> + <td>{{ proceedings.event_description|default:'-'|linebreaksbr }}</td> + </tr> + {% if proceedings.event_start_date %} + <tr> + <th>Event start date</th> + <td>{{ proceedings.event_start_date }}</td> + </tr> + {% endif %} + {% if proceedings.event_end_date %} + <tr> + <th>Event end date</th> + <td>{{ proceedings.event_end_date }}</td> + </tr> + {% endif %} + <tr> + <th>Guest Fellowships</th> + <td>{{ proceedings.fellowships.count }}</td> + </tr> + <tr> + <th>Lead Fellowship</th> + <td>{{ proceedings.lead_fellow }}</td> + </tr> + <tr> + <th>Submission Open</th> + <td>{{ proceedings.submissions_open }}</td> + </tr> + <tr> + <th>Submission Deadline</th> + <td>{{ proceedings.submissions_deadline }}</td> + </tr> + <tr> + <th>Submission Close</th> + <td>{{ proceedings.submissions_close }}</td> + </tr> +</table> diff --git a/proceedings/templates/proceedings/proceedings.html b/proceedings/templates/proceedings/proceedings.html new file mode 100644 index 0000000000000000000000000000000000000000..cbfac16b9d5a503543dc4ccada6e305a90a54922 --- /dev/null +++ b/proceedings/templates/proceedings/proceedings.html @@ -0,0 +1,42 @@ +{% extends 'submissions/admin/base.html' %} + +{% block breadcrumb_items %} + {{ block.super }} + <span class="breadcrumb-item">Proceedings</span> +{% endblock %} + +{% block pagetitle %}: Manage Proceedings{% endblock pagetitle %} + +{% block content %} + <h1>Manage Proceedings</h1> + <a href="{% url 'proceedings:proceedings_add' %}">Add new Proceedings</a> + + <table class="table mt-3"> + <thead> + <tr> + <th>Event name</th> + <th>Submission Deadline</th> + <th>Guest Fellowships</th> + <th>Submissions</th> + <th></th> + </tr> + </thead> + <tbody> + {% for proc in proceedings %} + <tr> + <td>{{ proc.event_name }}</td> + <td>{{ proc.submissions_deadline }}</td> + <td>{{ proc.fellowships.count }}</td> + <td>{{ proc.submissions.count }}</td> + <td> + <a href="{% url 'proceedings:proceedings_details' proc.id %}">View Proceedings details</a> + </td> + </tr> + {% empty %} + <tr> + <td class="text-danger py-2" colspan="5">There are no Proceedings!</td> + </tr> + {% endfor %} + </tbody> + </table> +{% endblock %} diff --git a/proceedings/templates/proceedings/proceedings_add.html b/proceedings/templates/proceedings/proceedings_add.html new file mode 100644 index 0000000000000000000000000000000000000000..5a5d195de8a740040ff343b7b39961408ed8cc52 --- /dev/null +++ b/proceedings/templates/proceedings/proceedings_add.html @@ -0,0 +1,22 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'proceedings:proceedings' %}" class="breadcrumb-item">Proceedings</a> + <span class="breadcrumb-item">Add new</span> +{% endblock %} + +{% block pagetitle %}: Add new Proceedings{% endblock pagetitle %} + +{% block content %} + <h1>Add new Proceedings</h1> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <button type="submit" class="btn btn-primary">Add Proceedings</button> + </form> + +{% endblock %} diff --git a/proceedings/templates/proceedings/proceedings_details.html b/proceedings/templates/proceedings/proceedings_details.html new file mode 100644 index 0000000000000000000000000000000000000000..f2efc0fbcb74d3d698d538608622de8a90fb11c0 --- /dev/null +++ b/proceedings/templates/proceedings/proceedings_details.html @@ -0,0 +1,84 @@ +{% extends 'submissions/admin/base.html' %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'proceedings:proceedings' %}" class="breadcrumb-item">Proceedings</a> + <span class="breadcrumb-item">Proceedings details</span> +{% endblock %} + +{% block pagetitle %}: Proceedings details{% endblock pagetitle %} + +{% block content %} + <h1>Proceedings details</h1> + <h2 class="text-primary">{{ proceedings }}</h2> + <br> + + {% include 'partials/proceedings/summary.html' with proceedings=proceedings %} + +{% comment %} + <form method="post" action="{% url 'colleges:fellowship_terminate' fellowship.id %}" class="d-inline"> + {% csrf_token %} + <button type="submit" class="btn btn-danger">Terminate Fellowship</button> + </form> + <a href="{% url 'colleges:fellowship_edit' fellowship.id %}" class="btn btn-info ml-2">Edit Fellowship</a> + {% endcomment %} + + + <h3 class="mt-3">All Guest Fellowships of this Proceedings</h3> + + <table class="table"> + <thead> + <tr> + <th>Fellowship ID</th> + <th>Fellow</th> + <th>Type</th> + <th colspan="2">Date range</th> + </tr> + </thead> + <tbody> + {% for fellowship in proceedings.fellowships.all %} + <tr> + <td>{{ fellowship.id }}</td> + <td>{{ fellowship.contributor }}</td> + <td>{{ fellowship.guest|yesno:"Guest fellowship,Regular fellowship"|safe }}</td> + <td> + {% if fellowship.start_date %} + from {{ fellowship.start_date }} + {% endif %} + {% if fellowship.until_date %} + until {{ fellowship.until_date }} + {% endif %} + {% if not fellowship.start_date and not fellowship.until_date %} + <i>Unlimited</i> + {% endif %} + </td> + <td><a href="{{ fellowship.get_absolute_url }}">See details</a></td> + </tr> + {% endfor %} + </tbody> + </table> + + <h3>All Submissions for this Proceedings Issue</h3> + <table class="table table-hover"> + <thead> + <tr> + <th>Submission</th> + <th>Author List</th> + <th colspan="2">Status</th> + </tr> + </thead> + <tbody> + {% for submission in proceedings.submissions.all %} + <tr> + <td> + <a href="{{ submission.get_absolute_url }}">{{ submission.arxiv_identifier_w_vn_nr }}, {{ submission.title|truncatechars:50 }}</a> + </td> + <td>{{ submission.author_list }}</td> + <td>{{ submission.get_status_display }}</td> + <td><a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a></td> + </tr> + {% endfor %} + </tbody> + </table> + +{% endblock %} diff --git a/proceedings/templates/proceedings/proceedings_edit.html b/proceedings/templates/proceedings/proceedings_edit.html new file mode 100644 index 0000000000000000000000000000000000000000..6b837910a45764d72eb469526df95ceb5560f006 --- /dev/null +++ b/proceedings/templates/proceedings/proceedings_edit.html @@ -0,0 +1,22 @@ +{% extends 'submissions/admin/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <a href="{% url 'proceedings:proceedings' %}" class="breadcrumb-item">Proceedings</a> + <span class="breadcrumb-item">Edit new</span> +{% endblock %} + +{% block pagetitle %}: Edit Proceedings{% endblock pagetitle %} + +{% block content %} + <h1>Edit Proceedings</h1> + + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <button type="submit" class="btn btn-primary">Save Proceedings</button> + </form> + +{% endblock %} diff --git a/proceedings/tests.py b/proceedings/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/proceedings/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/proceedings/urls.py b/proceedings/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..1f51ce041cb7d6b89feb0fdad2d7eff10376864e --- /dev/null +++ b/proceedings/urls.py @@ -0,0 +1,11 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + # Proceedings + url(r'^$', views.proceedings, name='proceedings'), + url(r'^add/$', views.ProceedingsAddView.as_view(), name='proceedings_add'), + url(r'^(?P<id>[0-9]+)/$', views.proceedings_details, name='proceedings_details'), + url(r'^(?P<id>[0-9]+)/edit$', views.ProceedingsUpdateView.as_view(), name='proceedings_edit'), +] diff --git a/proceedings/views.py b/proceedings/views.py new file mode 100644 index 0000000000000000000000000000000000000000..d2db1c612dc05c19bc59dfa538a63cfe36854bb5 --- /dev/null +++ b/proceedings/views.py @@ -0,0 +1,46 @@ +from django.contrib.auth.decorators import login_required, permission_required +from django.shortcuts import get_object_or_404, render +from django.views.generic.edit import CreateView, UpdateView + +from .forms import ProceedingsForm +from .models import Proceedings + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def proceedings(request): + """ + List all Proceedings + """ + context = { + 'proceedings': Proceedings.objects.all() + } + return render(request, 'proceedings/proceedings.html', context) + + +@login_required +@permission_required('scipost.can_manage_college_composition', raise_exception=True) +def proceedings_details(request, id): + """ + Show Proceedings details + """ + proceedings = get_object_or_404(Proceedings, id=id) + context = { + 'proceedings': proceedings + } + return render(request, 'proceedings/proceedings_details.html', context) + + +class ProceedingsAddView(CreateView): + models = Proceedings + form_class = ProceedingsForm + template_name = 'proceedings/proceedings_add.html' + + +class ProceedingsUpdateView(UpdateView): + models = Proceedings + form_class = ProceedingsForm + template_name = 'proceedings/proceedings_edit.html' + + def get_object(self): + return get_object_or_404(Proceedings, id=self.kwargs['id']) diff --git a/production/models.py b/production/models.py index 549027075dea4866f62f1cb3cc2d5620cfd60868..65ace229bff3e4de8987e7199005eeb600c4b2f6 100644 --- a/production/models.py +++ b/production/models.py @@ -70,6 +70,10 @@ class ProductionStream(models.Model): def completed(self): return self.status == PRODUCTION_STREAM_COMPLETED + @property + def notification_name(self): + return self.submission.arxiv_identifier_w_vn_nr + class ProductionEvent(models.Model): stream = models.ForeignKey(ProductionStream, on_delete=models.CASCADE, related_name='events') @@ -97,6 +101,10 @@ class ProductionEvent(models.Model): def editable(self): return self.event in [EVENT_MESSAGE, EVENT_HOUR_REGISTRATION] and not self.stream.completed + @property + def notification_name(self): + return self.stream.notification_name + def proofs_upload_location(instance, filename): submission = instance.stream.submission diff --git a/production/templates/production/partials/production_stream_card_completed.html b/production/templates/production/partials/production_stream_card_completed.html index fd91b061844a670150a47a19464e9ceaf26227a2..e938b1d37d4c21929b5156d3595f5f10fd54976b 100644 --- a/production/templates/production/partials/production_stream_card_completed.html +++ b/production/templates/production/partials/production_stream_card_completed.html @@ -4,8 +4,8 @@ {% get_obj_perms request.user for stream as "sub_perms" %} -<div class="card-body py-0" id="stream_{{stream.id}}"> - {% include 'submissions/_submission_card_content_sparse.html' with submission=stream.submission %} +<div class="card-body" id="stream_{{stream.id}}"> + {% include 'partials/submissions/submission_card_content.html' with submission=stream.submission %} </div> <div class="card-body"> <h3>Stream details</h3> diff --git a/production/templates/production/productionevent_confirm_delete.html b/production/templates/production/productionevent_confirm_delete.html index c6cd4c05a4da812c0739cc41bab2f72103b4f4ae..6661f0406c64a0637abe95540ca8bf4f8d2d2c27 100644 --- a/production/templates/production/productionevent_confirm_delete.html +++ b/production/templates/production/productionevent_confirm_delete.html @@ -12,7 +12,7 @@ <div class="row"> <div class="col-12"> <h1 class="highlight">Delete production event</h1> - {% include 'submissions/_submission_card_content_sparse.html' with submission=object.stream.submission %} + {% include 'partials/submissions/submission_card_content.html' with submission=object.stream.submission %} </div> </div> <div class="row"> diff --git a/production/templates/production/productionevent_form.html b/production/templates/production/productionevent_form.html index d520f1c75c2a200a9657e62dec024527fe0d1055..854949c7c79d35ecc6bbe178227d58327091d369 100644 --- a/production/templates/production/productionevent_form.html +++ b/production/templates/production/productionevent_form.html @@ -12,7 +12,7 @@ <div class="row"> <div class="col-12"> <h1 class="highlight">Edit production event</h1> - {% include 'submissions/_submission_card_content_sparse.html' with submission=object.stream.submission %} + {% include 'partials/submissions/submission_card_content.html' with submission=object.stream.submission %} </div> </div> <div class="row"> diff --git a/production/templates/production/proofs.html b/production/templates/production/proofs.html index 8a2f4071aadfd9296f1939117d332af4933f4738..bfbaa7937fdd75a7a6d0a230882174e77609428c 100644 --- a/production/templates/production/proofs.html +++ b/production/templates/production/proofs.html @@ -13,7 +13,7 @@ <div class="row"> <div class="col-12"> <h1 class="highlight">Proofs (version {{ proofs.version }})</h1> - {% include 'submissions/_submission_card_content_sparse.html' with submission=stream.submission %} + {% include 'partials/submissions/submission_card_content.html' with submission=stream.submission %} </div> </div> <div class="row"> diff --git a/production/templates/production/upload_proofs.html b/production/templates/production/upload_proofs.html index 09970ec96a500852c38c7b745db653ec10f0c9d9..55efa68990e527c266748dbedc5dea085a9a4714 100644 --- a/production/templates/production/upload_proofs.html +++ b/production/templates/production/upload_proofs.html @@ -12,7 +12,7 @@ <div class="row"> <div class="col-12"> <h1 class="highlight">Upload Proofs</h1> - {% include 'submissions/_submission_card_content_sparse.html' with submission=stream.submission %} + {% include 'partials/submissions/submission_card_content.html' with submission=stream.submission %} </div> </div> <div class="row"> diff --git a/scipost/db/constants_migration_0043.py b/scipost/db/constants_migration_0043.py deleted file mode 100644 index deeea736aa2e6bd5cf8bc87c293bb76fabddb815..0000000000000000000000000000000000000000 --- a/scipost/db/constants_migration_0043.py +++ /dev/null @@ -1,49 +0,0 @@ -collegeMembers = ( - {'name': 'Sabine Andergassen', 'title': 'Prof.', 'link': 'https://www.uni-tuebingen.de/en/faculties/faculty-of-science/departments/physics/institutes/institute-for-theoretical-physics/research-groups/andergassen-group.html', 'subtitle': 'Tübingen'}, - {'name': 'Fakher Assaad', 'title': 'Prof.', 'link': 'http://www.physik.uni-wuerzburg.de/~assaad/', 'subtitle': 'Würzbrug'}, - {'name': 'Claudio Attaccalite', 'title': 'Dr', 'link': 'http://www.attaccalite.com', 'subtitle': 'Marseille'}, - {'name': 'Denis Bartolo', 'title': 'Prof.', 'link': 'https://denis114.wordpress.com', 'subtitle': 'ENS Lyon'}, - {'name': 'Laura Baudis', 'title': 'Prof.', 'link': 'http://www.physik.unizh.ch/~lbaudis/index.html', 'subtitle': 'Zurich'}, - {'title': 'Prof.', 'link': 'http://www.lorentz.leidenuniv.nl/beenakker/', 'subtitle': 'Leiden', 'name': 'Carlo Beenakker'}, - {'title': 'Prof.', 'link': 'https://www.coulomb.univ-montp2.fr/perso/ludovic.berthier/', 'subtitle': 'Montpellier', 'name': 'Ludovic Berthier'}, - {'title': 'Prof.', 'link': 'http://ipht.cea.fr/Pisp/giulio.biroli/index_en.php', 'subtitle': 'CEA Saclay', 'name': 'Giulio Biroli'}, - {'title': 'Prof.', 'link': 'http://www.en.physik.uni-muenchen.de/personen/professoren/bloch/index.html', 'subtitle': 'LMU Munich', 'name': 'Immanuel Bloch'}, - {'title': 'Prof.', 'link': 'https://staff.fnwi.uva.nl/j.deboer/', 'subtitle': 'U. van Amsterdam', 'name': 'Jan de Boer'}, - {'title': 'Prof.', 'link': 'http://www.uva.nl/en/about-the-uva/organisation/staff-members/content/b/o/d.bonn/d.bonn.html', 'subtitle': 'U. van Amsterdam', 'name': 'Daniel Bonn'}, - {'title': 'Prof.', 'link': 'http://www.statphys.sissa.it/wordpress/?page_id=1731', 'subtitle': 'SISSA', 'name': 'Pasquale Calabrese'}, - {'title': 'Prof.', 'link': 'http://personalpages.to.infn.it/~caselle/index_en.html', 'subtitle': 'Torino', 'name': 'Michele Caselle'}, - {'title': 'Prof.', 'link': 'http://www.saha.ac.in/cmp/bikask.chakrabarti/bikas.html', 'subtitle': 'Kolkata', 'name': 'Bikas Chakrabarti'}, - {'title': 'Prof.', 'link': 'http://www.tcm.phy.cam.ac.uk/~nrc25/', 'subtitle': 'Cambridge', 'name': 'Nigel Cooper'}, - {'title': 'Prof.', 'link': 'http://physics.cornell.edu/csaba-csaki', 'subtitle': 'Cornell', 'name': 'Csaba Csaki'}, - {'title': 'Prof.', 'link': 'http://theory.tifr.res.in/~kedar/', 'subtitle': 'TIFR Mumbai', 'name': 'Kedar Damle'}, - {'title': 'Prof.', 'link': 'http://researchers.uq.edu.au/researcher/1134', 'subtitle': 'U. of Queensland', 'name': 'Matthew Davis'}, - {'title': 'Prof.', 'link': 'http://www-thphys.physics.ox.ac.uk/people/FabianEssler/', 'subtitle': 'U. of Oxford', 'name': 'Fabian Essler'}, - {'title': 'Prof.', 'link': 'http://www.pd.infn.it/~feruglio/', 'subtitle': 'Padova, INFN', 'name': 'Ferruccio Feruglio'}, - {'title': 'Prof.', 'link': 'http://www.ms.unimelb.edu.au/~jdgier@unimelb/', 'subtitle': 'U. of Melbourne', 'name': 'Jan de Gier'}, - {'title': 'Prof.', 'link': 'http://www.desy.de/about_desy/leading_scientists/beate_heinemann/index_eng.html', 'subtitle': 'DESY; Freiburg', 'name': 'Beate Heinemann'}, - {'title': 'Prof.', 'link': 'http://katzgraber.org', 'subtitle': 'Texas A&M', 'name': 'Helmut Katzgraber'}, - {'title': 'Prof.', 'link': 'https://web.physik.rwth-aachen.de/~mkraemer/', 'subtitle': 'RWTH Aachen', 'name': 'Michael Krämer'}, - {'title': 'Prof.', 'link': 'https://www.pmmh.espci.fr/~jorge/', 'subtitle': 'PMMH Paris, CNRS', 'name': 'Jorge Kurchan'}, - {'title': 'Prof.', 'link': 'https://vivo.brown.edu/display/glandsbe', 'subtitle': 'Brown Univ.', 'name': 'Greg Landsberg'}, - {'title': 'Prof.', 'link': 'https://www.mpg.de/6812374/chem_physik_fester_stoffe_mackenzie', 'subtitle': 'MPICPS Dresden, St-Andrews', 'name': 'Andrew P. MacKenzie'}, - {'title': 'Prof.', 'link': 'http://www.ens-lyon.fr/PHYSIQUE/presentation/annuaire/maillet-jean-michel', 'subtitle': 'ENS Lyon', 'name': 'Jean Michel Maillet'}, - {'title': 'Prof.', 'link': 'https://www.mpg.de/343435/physik_komplexer_systeme_wissM28', 'subtitle': 'MPIPKS Dresden', 'name': 'Roderich Moessner'}, - {'title': 'Prof.', 'link': 'https://www.uibk.ac.at/exphys/ultracold/people/christoph.naegerl/', 'subtitle': 'Innsbruck', 'name': 'Hanns-Christoph Nägerl'}, - {'title': 'Prof.', 'link': 'http://www.physics.miami.edu/~nepomechie/', 'subtitle': 'U. of Miami', 'name': 'Rafael Nepomechie'}, - {'title': 'Prof.', 'link': 'https://staff.fnwi.uva.nl/b.nienhuis/', 'subtitle': 'U. van Amsterdam', 'name': 'Bernard Nienhuis'}, - {'title': 'Prof.', 'link': 'http://www.lpthe.jussieu.fr/~pioline/', 'subtitle': 'LPTHE Jussieu', 'name': 'Boris Pioline'}, - {'title': 'Prof.', 'link': 'https://www.uu.nl/staff/RHHGvanRoij/0', 'subtitle': 'Utrecht', 'name': 'René van Roij'}, - {'title': 'Prof.', 'link': 'http://www.thp.uni-koeln.de/rosch', 'subtitle': 'U. of Cologne', 'name': 'Achim Rosch'}, - {'title': 'Prof.', 'link': 'http://saleur.sandvox.net', 'subtitle': 'CEA Saclay/USC', 'name': 'Hubert Saleur'}, - {'title': 'Prof.', 'link': 'http://www.phy.ohiou.edu/people/faculty/sandler.html', 'subtitle': 'Ohio', 'name': 'Nancy Sandler'}, - {'title': 'Dr.', 'link': 'http://www.sussex.ac.uk/profiles/320359', 'subtitle': 'Sussex', 'name': 'Veronica Sanz'}, - {'title': 'Prof.', 'link': 'http://www-thphys.physics.ox.ac.uk/people/SubirSarkar/', 'subtitle': 'Oxford; Niels Bohr Institute', 'name': 'Subir Sarkar'}, - {'title': 'Prof.', 'link': 'https://staff.fnwi.uva.nl/c.j.m.schoutens/', 'subtitle': 'U. van Amsterdam', 'name': 'Kareljan Schoutens'}, - {'title': 'Dr', 'link': 'http://www.phys.ens.fr/~guilhem/', 'subtitle': 'ENS Paris', 'name': 'Guilhem Semerjian'}, - {'title': 'Prof.', 'link': 'http://www-thphys.physics.ox.ac.uk/people/SteveSimon/', 'subtitle': 'U. of Oxford', 'name': 'Steve Simon'}, - {'title': 'Prof.', 'link': 'http://bec.science.unitn.it/infm-bec/people/stringari.html', 'subtitle': 'Trento', 'name': 'Sandro Stringari'}, - {'title': 'Prof.', 'link': 'http://www.damtp.cam.ac.uk/user/tong/', 'subtitle': 'Cambridge', 'name': 'David Tong'}, - {'title': 'Prof.', 'link': 'http://www.physique.usherbrooke.ca/pages/en/node/3412', 'subtitle': 'Sherbrooke', 'name': 'André-Marie Tremblay'}, - {'title': 'Prof.', 'link': 'http://trivediresearch.org.ohio-state.edu', 'subtitle': 'Ohio State U.', 'name': 'Nandini Trivedi'}, - {'title': 'Prof.', 'link': 'http://vergassolalab.ucsd.edu', 'subtitle': 'UC Sand Diego', 'name': 'Massimo Vergassola'}, -) diff --git a/scipost/fixtures/contributors.json b/scipost/fixtures/contributors.json deleted file mode 100644 index a4863604278b1460829d963d108b4db098579aef..0000000000000000000000000000000000000000 --- a/scipost/fixtures/contributors.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "model": "auth.user", - "pk": 1, - "fields": { - "password": "pbkdf2_sha256$30000$iqtXX60Ahqcx$IKfNZNSMbSca/agzPXHTdEej3dXhQi1sK/MCrBTnuW4=", - "last_login": null, - "is_superuser": false, - "username": "Test", - "first_name": "Firstname", - "last_name": "Testuser", - "email": "testuser@test.com", - "is_staff": false, - "is_active": true, - "date_joined": "2016-12-14T20:41:31.282Z", - "groups": [ - 6 - ], - "user_permissions": [] - } - }, - { - "model": "scipost.contributor", - "pk": 2, - "fields": { - "user": 1, - "status": 1, - "title": "MR", - "vetted_by": 2 - } - } -] diff --git a/scipost/fixtures/groups.json b/scipost/fixtures/groups.json deleted file mode 100644 index 82fafdc4738001941947ba92ecf8d9a5749ad11d..0000000000000000000000000000000000000000 --- a/scipost/fixtures/groups.json +++ /dev/null @@ -1,116 +0,0 @@ -[ -{ - "model": "auth.group", - "pk": 1, - "fields": { - "name": "SciPost Administrators", - "permissions": [ - 143, - 130, - 131, - 148, - 128, - 147, - 139, - 137, - 140, - 126, - 138, - 142 - ] - } -}, -{ - "model": "auth.group", - "pk": 2, - "fields": { - "name": "Advisory Board", - "permissions": [ - 128 - ] - } -}, -{ - "model": "auth.group", - "pk": 3, - "fields": { - "name": "Editorial Administrators", - "permissions": [ - 143, - 148, - 147, - 149, - 142 - ] - } -}, -{ - "model": "auth.group", - "pk": 4, - "fields": { - "name": "Editorial College", - "permissions": [ - 144, - 145, - 142, - 132 - ] - } -}, -{ - "model": "auth.group", - "pk": 5, - "fields": { - "name": "Vetting Editors", - "permissions": [ - 139, - 137, - 140, - 138 - ] - } -}, -{ - "model": "auth.group", - "pk": 6, - "fields": { - "name": "Registered Contributors", - "permissions": [ - 134, - 146, - 135, - 136, - 133, - 141 - ] - } -}, -{ - "model": "auth.group", - "pk": 7, - "fields": { - "name": "Testers", - "permissions": [] - } -}, -{ - "model": "auth.group", - "pk": 8, - "fields": { - "name": "Ambassadors", - "permissions": [ - 128 - ] - } -}, -{ - "model": "auth.group", - "pk": 9, - "fields": { - "name": "Junior Ambassadors", - "permissions": [ - 127 - ] - } -} -] diff --git a/scipost/fixtures/permissions.json b/scipost/fixtures/permissions.json deleted file mode 100644 index a718c3476c978d97c20a15d8b81f01ac0500596f..0000000000000000000000000000000000000000 --- a/scipost/fixtures/permissions.json +++ /dev/null @@ -1,1343 +0,0 @@ -[ -{ - "model": "auth.permission", - "pk": 1, - "fields": { - "name": "Can add log entry", - "content_type": 1, - "codename": "add_logentry" - } -}, -{ - "model": "auth.permission", - "pk": 2, - "fields": { - "name": "Can change log entry", - "content_type": 1, - "codename": "change_logentry" - } -}, -{ - "model": "auth.permission", - "pk": 3, - "fields": { - "name": "Can delete log entry", - "content_type": 1, - "codename": "delete_logentry" - } -}, -{ - "model": "auth.permission", - "pk": 4, - "fields": { - "name": "Can add user", - "content_type": 2, - "codename": "add_user" - } -}, -{ - "model": "auth.permission", - "pk": 5, - "fields": { - "name": "Can change user", - "content_type": 2, - "codename": "change_user" - } -}, -{ - "model": "auth.permission", - "pk": 6, - "fields": { - "name": "Can delete user", - "content_type": 2, - "codename": "delete_user" - } -}, -{ - "model": "auth.permission", - "pk": 7, - "fields": { - "name": "Can add group", - "content_type": 3, - "codename": "add_group" - } -}, -{ - "model": "auth.permission", - "pk": 8, - "fields": { - "name": "Can change group", - "content_type": 3, - "codename": "change_group" - } -}, -{ - "model": "auth.permission", - "pk": 9, - "fields": { - "name": "Can delete group", - "content_type": 3, - "codename": "delete_group" - } -}, -{ - "model": "auth.permission", - "pk": 10, - "fields": { - "name": "Can add permission", - "content_type": 4, - "codename": "add_permission" - } -}, -{ - "model": "auth.permission", - "pk": 11, - "fields": { - "name": "Can change permission", - "content_type": 4, - "codename": "change_permission" - } -}, -{ - "model": "auth.permission", - "pk": 12, - "fields": { - "name": "Can delete permission", - "content_type": 4, - "codename": "delete_permission" - } -}, -{ - "model": "auth.permission", - "pk": 13, - "fields": { - "name": "Can add content type", - "content_type": 5, - "codename": "add_contenttype" - } -}, -{ - "model": "auth.permission", - "pk": 14, - "fields": { - "name": "Can change content type", - "content_type": 5, - "codename": "change_contenttype" - } -}, -{ - "model": "auth.permission", - "pk": 15, - "fields": { - "name": "Can delete content type", - "content_type": 5, - "codename": "delete_contenttype" - } -}, -{ - "model": "auth.permission", - "pk": 16, - "fields": { - "name": "Can add session", - "content_type": 6, - "codename": "add_session" - } -}, -{ - "model": "auth.permission", - "pk": 17, - "fields": { - "name": "Can change session", - "content_type": 6, - "codename": "change_session" - } -}, -{ - "model": "auth.permission", - "pk": 18, - "fields": { - "name": "Can delete session", - "content_type": 6, - "codename": "delete_session" - } -}, -{ - "model": "auth.permission", - "pk": 19, - "fields": { - "name": "Can add captcha store", - "content_type": 7, - "codename": "add_captchastore" - } -}, -{ - "model": "auth.permission", - "pk": 20, - "fields": { - "name": "Can change captcha store", - "content_type": 7, - "codename": "change_captchastore" - } -}, -{ - "model": "auth.permission", - "pk": 21, - "fields": { - "name": "Can delete captcha store", - "content_type": 7, - "codename": "delete_captchastore" - } -}, -{ - "model": "auth.permission", - "pk": 22, - "fields": { - "name": "Can add user object permission", - "content_type": 8, - "codename": "add_userobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 23, - "fields": { - "name": "Can change user object permission", - "content_type": 8, - "codename": "change_userobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 24, - "fields": { - "name": "Can delete user object permission", - "content_type": 8, - "codename": "delete_userobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 25, - "fields": { - "name": "Can add group object permission", - "content_type": 9, - "codename": "add_groupobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 26, - "fields": { - "name": "Can change group object permission", - "content_type": 9, - "codename": "change_groupobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 27, - "fields": { - "name": "Can delete group object permission", - "content_type": 9, - "codename": "delete_groupobjectpermission" - } -}, -{ - "model": "auth.permission", - "pk": 28, - "fields": { - "name": "Can add commentary", - "content_type": 10, - "codename": "add_commentary" - } -}, -{ - "model": "auth.permission", - "pk": 29, - "fields": { - "name": "Can change commentary", - "content_type": 10, - "codename": "change_commentary" - } -}, -{ - "model": "auth.permission", - "pk": 30, - "fields": { - "name": "Can delete commentary", - "content_type": 10, - "codename": "delete_commentary" - } -}, -{ - "model": "auth.permission", - "pk": 31, - "fields": { - "name": "Can add comment", - "content_type": 11, - "codename": "add_comment" - } -}, -{ - "model": "auth.permission", - "pk": 32, - "fields": { - "name": "Can change comment", - "content_type": 11, - "codename": "change_comment" - } -}, -{ - "model": "auth.permission", - "pk": 33, - "fields": { - "name": "Can delete comment", - "content_type": 11, - "codename": "delete_comment" - } -}, -{ - "model": "auth.permission", - "pk": 34, - "fields": { - "name": "Can add issue", - "content_type": 12, - "codename": "add_issue" - } -}, -{ - "model": "auth.permission", - "pk": 35, - "fields": { - "name": "Can change issue", - "content_type": 12, - "codename": "change_issue" - } -}, -{ - "model": "auth.permission", - "pk": 36, - "fields": { - "name": "Can delete issue", - "content_type": 12, - "codename": "delete_issue" - } -}, -{ - "model": "auth.permission", - "pk": 37, - "fields": { - "name": "Can add journal", - "content_type": 13, - "codename": "add_journal" - } -}, -{ - "model": "auth.permission", - "pk": 38, - "fields": { - "name": "Can change journal", - "content_type": 13, - "codename": "change_journal" - } -}, -{ - "model": "auth.permission", - "pk": 39, - "fields": { - "name": "Can delete journal", - "content_type": 13, - "codename": "delete_journal" - } -}, -{ - "model": "auth.permission", - "pk": 40, - "fields": { - "name": "Can add unregistered author", - "content_type": 14, - "codename": "add_unregisteredauthor" - } -}, -{ - "model": "auth.permission", - "pk": 41, - "fields": { - "name": "Can change unregistered author", - "content_type": 14, - "codename": "change_unregisteredauthor" - } -}, -{ - "model": "auth.permission", - "pk": 42, - "fields": { - "name": "Can delete unregistered author", - "content_type": 14, - "codename": "delete_unregisteredauthor" - } -}, -{ - "model": "auth.permission", - "pk": 43, - "fields": { - "name": "Can add deposit", - "content_type": 15, - "codename": "add_deposit" - } -}, -{ - "model": "auth.permission", - "pk": 44, - "fields": { - "name": "Can change deposit", - "content_type": 15, - "codename": "change_deposit" - } -}, -{ - "model": "auth.permission", - "pk": 45, - "fields": { - "name": "Can delete deposit", - "content_type": 15, - "codename": "delete_deposit" - } -}, -{ - "model": "auth.permission", - "pk": 46, - "fields": { - "name": "Can add publication", - "content_type": 16, - "codename": "add_publication" - } -}, -{ - "model": "auth.permission", - "pk": 47, - "fields": { - "name": "Can change publication", - "content_type": 16, - "codename": "change_publication" - } -}, -{ - "model": "auth.permission", - "pk": 48, - "fields": { - "name": "Can delete publication", - "content_type": 16, - "codename": "delete_publication" - } -}, -{ - "model": "auth.permission", - "pk": 49, - "fields": { - "name": "Can add volume", - "content_type": 17, - "codename": "add_volume" - } -}, -{ - "model": "auth.permission", - "pk": 50, - "fields": { - "name": "Can change volume", - "content_type": 17, - "codename": "change_volume" - } -}, -{ - "model": "auth.permission", - "pk": 51, - "fields": { - "name": "Can delete volume", - "content_type": 17, - "codename": "delete_volume" - } -}, -{ - "model": "auth.permission", - "pk": 52, - "fields": { - "name": "Can add news item", - "content_type": 18, - "codename": "add_newsitem" - } -}, -{ - "model": "auth.permission", - "pk": 53, - "fields": { - "name": "Can change news item", - "content_type": 18, - "codename": "change_newsitem" - } -}, -{ - "model": "auth.permission", - "pk": 54, - "fields": { - "name": "Can delete news item", - "content_type": 18, - "codename": "delete_newsitem" - } -}, -{ - "model": "auth.permission", - "pk": 55, - "fields": { - "name": "Can add precooked email", - "content_type": 19, - "codename": "add_precookedemail" - } -}, -{ - "model": "auth.permission", - "pk": 56, - "fields": { - "name": "Can change precooked email", - "content_type": 19, - "codename": "change_precookedemail" - } -}, -{ - "model": "auth.permission", - "pk": 57, - "fields": { - "name": "Can delete precooked email", - "content_type": 19, - "codename": "delete_precookedemail" - } -}, -{ - "model": "auth.permission", - "pk": 58, - "fields": { - "name": "Can add affiliation object", - "content_type": 20, - "codename": "add_affiliationobject" - } -}, -{ - "model": "auth.permission", - "pk": 59, - "fields": { - "name": "Can change affiliation object", - "content_type": 20, - "codename": "change_affiliationobject" - } -}, -{ - "model": "auth.permission", - "pk": 60, - "fields": { - "name": "Can delete affiliation object", - "content_type": 20, - "codename": "delete_affiliationobject" - } -}, -{ - "model": "auth.permission", - "pk": 61, - "fields": { - "name": "Can add registration invitation", - "content_type": 21, - "codename": "add_registrationinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 62, - "fields": { - "name": "Can change registration invitation", - "content_type": 21, - "codename": "change_registrationinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 63, - "fields": { - "name": "Can delete registration invitation", - "content_type": 21, - "codename": "delete_registrationinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 64, - "fields": { - "name": "Can add spb membership agreement", - "content_type": 22, - "codename": "add_spbmembershipagreement" - } -}, -{ - "model": "auth.permission", - "pk": 65, - "fields": { - "name": "Can change spb membership agreement", - "content_type": 22, - "codename": "change_spbmembershipagreement" - } -}, -{ - "model": "auth.permission", - "pk": 66, - "fields": { - "name": "Can delete spb membership agreement", - "content_type": 22, - "codename": "delete_spbmembershipagreement" - } -}, -{ - "model": "auth.permission", - "pk": 67, - "fields": { - "name": "Can add supporting partner", - "content_type": 23, - "codename": "add_supportingpartner" - } -}, -{ - "model": "auth.permission", - "pk": 68, - "fields": { - "name": "Can change supporting partner", - "content_type": 23, - "codename": "change_supportingpartner" - } -}, -{ - "model": "auth.permission", - "pk": 69, - "fields": { - "name": "Can delete supporting partner", - "content_type": 23, - "codename": "delete_supportingpartner" - } -}, -{ - "model": "auth.permission", - "pk": 70, - "fields": { - "name": "Can add arc", - "content_type": 24, - "codename": "add_arc" - } -}, -{ - "model": "auth.permission", - "pk": 71, - "fields": { - "name": "Can change arc", - "content_type": 24, - "codename": "change_arc" - } -}, -{ - "model": "auth.permission", - "pk": 72, - "fields": { - "name": "Can delete arc", - "content_type": 24, - "codename": "delete_arc" - } -}, -{ - "model": "auth.permission", - "pk": 73, - "fields": { - "name": "Can add graph", - "content_type": 25, - "codename": "add_graph" - } -}, -{ - "model": "auth.permission", - "pk": 74, - "fields": { - "name": "Can view graph", - "content_type": 25, - "codename": "view_graph" - } -}, -{ - "model": "auth.permission", - "pk": 75, - "fields": { - "name": "Can change graph", - "content_type": 25, - "codename": "change_graph" - } -}, -{ - "model": "auth.permission", - "pk": 76, - "fields": { - "name": "Can delete graph", - "content_type": 25, - "codename": "delete_graph" - } -}, -{ - "model": "auth.permission", - "pk": 77, - "fields": { - "name": "Can add contributor", - "content_type": 26, - "codename": "add_contributor" - } -}, -{ - "model": "auth.permission", - "pk": 78, - "fields": { - "name": "Can change contributor", - "content_type": 26, - "codename": "change_contributor" - } -}, -{ - "model": "auth.permission", - "pk": 79, - "fields": { - "name": "Can delete contributor", - "content_type": 26, - "codename": "delete_contributor" - } -}, -{ - "model": "auth.permission", - "pk": 80, - "fields": { - "name": "Can add authorship claim", - "content_type": 27, - "codename": "add_authorshipclaim" - } -}, -{ - "model": "auth.permission", - "pk": 81, - "fields": { - "name": "Can change authorship claim", - "content_type": 27, - "codename": "change_authorshipclaim" - } -}, -{ - "model": "auth.permission", - "pk": 82, - "fields": { - "name": "Can delete authorship claim", - "content_type": 27, - "codename": "delete_authorshipclaim" - } -}, -{ - "model": "auth.permission", - "pk": 83, - "fields": { - "name": "Can add unavailability period", - "content_type": 28, - "codename": "add_unavailabilityperiod" - } -}, -{ - "model": "auth.permission", - "pk": 84, - "fields": { - "name": "Can change unavailability period", - "content_type": 28, - "codename": "change_unavailabilityperiod" - } -}, -{ - "model": "auth.permission", - "pk": 85, - "fields": { - "name": "Can delete unavailability period", - "content_type": 28, - "codename": "delete_unavailabilityperiod" - } -}, -{ - "model": "auth.permission", - "pk": 86, - "fields": { - "name": "Can add list", - "content_type": 29, - "codename": "add_list" - } -}, -{ - "model": "auth.permission", - "pk": 87, - "fields": { - "name": "Can view list", - "content_type": 29, - "codename": "view_list" - } -}, -{ - "model": "auth.permission", - "pk": 88, - "fields": { - "name": "Can change list", - "content_type": 29, - "codename": "change_list" - } -}, -{ - "model": "auth.permission", - "pk": 89, - "fields": { - "name": "Can delete list", - "content_type": 29, - "codename": "delete_list" - } -}, -{ - "model": "auth.permission", - "pk": 90, - "fields": { - "name": "Can add node", - "content_type": 30, - "codename": "add_node" - } -}, -{ - "model": "auth.permission", - "pk": 91, - "fields": { - "name": "Can view node", - "content_type": 30, - "codename": "view_node" - } -}, -{ - "model": "auth.permission", - "pk": 92, - "fields": { - "name": "Can change node", - "content_type": 30, - "codename": "change_node" - } -}, -{ - "model": "auth.permission", - "pk": 93, - "fields": { - "name": "Can delete node", - "content_type": 30, - "codename": "delete_node" - } -}, -{ - "model": "auth.permission", - "pk": 94, - "fields": { - "name": "Can add draft invitation", - "content_type": 31, - "codename": "add_draftinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 95, - "fields": { - "name": "Can change draft invitation", - "content_type": 31, - "codename": "change_draftinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 96, - "fields": { - "name": "Can delete draft invitation", - "content_type": 31, - "codename": "delete_draftinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 97, - "fields": { - "name": "Can add team", - "content_type": 32, - "codename": "add_team" - } -}, -{ - "model": "auth.permission", - "pk": 98, - "fields": { - "name": "Can view team", - "content_type": 32, - "codename": "view_team" - } -}, -{ - "model": "auth.permission", - "pk": 99, - "fields": { - "name": "Can change team", - "content_type": 32, - "codename": "change_team" - } -}, -{ - "model": "auth.permission", - "pk": 100, - "fields": { - "name": "Can delete team", - "content_type": 32, - "codename": "delete_team" - } -}, -{ - "model": "auth.permission", - "pk": 101, - "fields": { - "name": "Can add remark", - "content_type": 33, - "codename": "add_remark" - } -}, -{ - "model": "auth.permission", - "pk": 102, - "fields": { - "name": "Can change remark", - "content_type": 33, - "codename": "change_remark" - } -}, -{ - "model": "auth.permission", - "pk": 103, - "fields": { - "name": "Can delete remark", - "content_type": 33, - "codename": "delete_remark" - } -}, -{ - "model": "auth.permission", - "pk": 104, - "fields": { - "name": "Can add editorial communication", - "content_type": 34, - "codename": "add_editorialcommunication" - } -}, -{ - "model": "auth.permission", - "pk": 105, - "fields": { - "name": "Can change editorial communication", - "content_type": 34, - "codename": "change_editorialcommunication" - } -}, -{ - "model": "auth.permission", - "pk": 106, - "fields": { - "name": "Can delete editorial communication", - "content_type": 34, - "codename": "delete_editorialcommunication" - } -}, -{ - "model": "auth.permission", - "pk": 107, - "fields": { - "name": "Can add referee invitation", - "content_type": 35, - "codename": "add_refereeinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 108, - "fields": { - "name": "Can change referee invitation", - "content_type": 35, - "codename": "change_refereeinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 109, - "fields": { - "name": "Can delete referee invitation", - "content_type": 35, - "codename": "delete_refereeinvitation" - } -}, -{ - "model": "auth.permission", - "pk": 110, - "fields": { - "name": "Can add submission", - "content_type": 36, - "codename": "add_submission" - } -}, -{ - "model": "auth.permission", - "pk": 111, - "fields": { - "name": "Can change submission", - "content_type": 36, - "codename": "change_submission" - } -}, -{ - "model": "auth.permission", - "pk": 112, - "fields": { - "name": "Can delete submission", - "content_type": 36, - "codename": "delete_submission" - } -}, -{ - "model": "auth.permission", - "pk": 113, - "fields": { - "name": "Can take editorial actions", - "content_type": 36, - "codename": "can_take_editorial_actions" - } -}, -{ - "model": "auth.permission", - "pk": 114, - "fields": { - "name": "Can add report", - "content_type": 37, - "codename": "add_report" - } -}, -{ - "model": "auth.permission", - "pk": 115, - "fields": { - "name": "Can change report", - "content_type": 37, - "codename": "change_report" - } -}, -{ - "model": "auth.permission", - "pk": 116, - "fields": { - "name": "Can delete report", - "content_type": 37, - "codename": "delete_report" - } -}, -{ - "model": "auth.permission", - "pk": 117, - "fields": { - "name": "Can add eic recommendation", - "content_type": 38, - "codename": "add_eicrecommendation" - } -}, -{ - "model": "auth.permission", - "pk": 118, - "fields": { - "name": "Can change eic recommendation", - "content_type": 38, - "codename": "change_eicrecommendation" - } -}, -{ - "model": "auth.permission", - "pk": 119, - "fields": { - "name": "Can delete eic recommendation", - "content_type": 38, - "codename": "delete_eicrecommendation" - } -}, -{ - "model": "auth.permission", - "pk": 120, - "fields": { - "name": "Can add editorial assignment", - "content_type": 39, - "codename": "add_editorialassignment" - } -}, -{ - "model": "auth.permission", - "pk": 121, - "fields": { - "name": "Can change editorial assignment", - "content_type": 39, - "codename": "change_editorialassignment" - } -}, -{ - "model": "auth.permission", - "pk": 122, - "fields": { - "name": "Can delete editorial assignment", - "content_type": 39, - "codename": "delete_editorialassignment" - } -}, -{ - "model": "auth.permission", - "pk": 123, - "fields": { - "name": "Can add thesis link", - "content_type": 40, - "codename": "add_thesislink" - } -}, -{ - "model": "auth.permission", - "pk": 124, - "fields": { - "name": "Can change thesis link", - "content_type": 40, - "codename": "change_thesislink" - } -}, -{ - "model": "auth.permission", - "pk": 125, - "fields": { - "name": "Can delete thesis link", - "content_type": 40, - "codename": "delete_thesislink" - } -}, -{ - "model": "auth.permission", - "pk": 126, - "fields": { - "name": "Can vet registration requests", - "content_type": 26, - "codename": "can_vet_registration_requests" - } -}, -{ - "model": "auth.permission", - "pk": 127, - "fields": { - "name": "Can draft registration invitations", - "content_type": 26, - "codename": "can_draft_registration_invitations" - } -}, -{ - "model": "auth.permission", - "pk": 128, - "fields": { - "name": "Can manage registration invitations", - "content_type": 26, - "codename": "can_manage_registration_invitations" - } -}, -{ - "model": "auth.permission", - "pk": 129, - "fields": { - "name": "Can invite Fellows", - "content_type": 26, - "codename": "can_invite_Fellows" - } -}, -{ - "model": "auth.permission", - "pk": 130, - "fields": { - "name": "Can email group members", - "content_type": 26, - "codename": "can_email_group_members" - } -}, -{ - "model": "auth.permission", - "pk": 131, - "fields": { - "name": "Can email particulars", - "content_type": 26, - "codename": "can_email_particulars" - } -}, -{ - "model": "auth.permission", - "pk": 132, - "fields": { - "name": "Can view By-laws of Editorial College", - "content_type": 26, - "codename": "view_bylaws" - } -}, -{ - "model": "auth.permission", - "pk": 133, - "fields": { - "name": "Can submit Comments", - "content_type": 26, - "codename": "can_submit_comments" - } -}, -{ - "model": "auth.permission", - "pk": 134, - "fields": { - "name": "Can express opinion on Comments", - "content_type": 26, - "codename": "can_express_opinion_on_comments" - } -}, -{ - "model": "auth.permission", - "pk": 135, - "fields": { - "name": "Can request opening of Commentara Pages", - "content_type": 26, - "codename": "can_request_commentary_pages" - } -}, -{ - "model": "auth.permission", - "pk": 136, - "fields": { - "name": "Can request Thesis Links", - "content_type": 26, - "codename": "can_request_thesislinks" - } -}, -{ - "model": "auth.permission", - "pk": 137, - "fields": { - "name": "Can vet Commentary page requests", - "content_type": 26, - "codename": "can_vet_commentary_requests" - } -}, -{ - "model": "auth.permission", - "pk": 138, - "fields": { - "name": "Can vet Thesis Link requests", - "content_type": 26, - "codename": "can_vet_thesislink_requests" - } -}, -{ - "model": "auth.permission", - "pk": 139, - "fields": { - "name": "Can vet Authorship claims", - "content_type": 26, - "codename": "can_vet_authorship_claims" - } -}, -{ - "model": "auth.permission", - "pk": 140, - "fields": { - "name": "Can vet submitted Comments", - "content_type": 26, - "codename": "can_vet_comments" - } -}, -{ - "model": "auth.permission", - "pk": 141, - "fields": { - "name": "Can submit manuscript", - "content_type": 26, - "codename": "can_submit_manuscript" - } -}, -{ - "model": "auth.permission", - "pk": 142, - "fields": { - "name": "Can view Submissions Pool", - "content_type": 26, - "codename": "can_view_pool" - } -}, -{ - "model": "auth.permission", - "pk": 143, - "fields": { - "name": "Can assign incoming Submissions to potential Editor-in-charge", - "content_type": 26, - "codename": "can_assign_submissions" - } -}, -{ - "model": "auth.permission", - "pk": 144, - "fields": { - "name": "Can take charge (become Editor-in-charge) of submissions", - "content_type": 26, - "codename": "can_take_charge_of_submissions" - } -}, -{ - "model": "auth.permission", - "pk": 145, - "fields": { - "name": "Can vet submitted Reports", - "content_type": 26, - "codename": "can_vet_submitted_reports" - } -}, -{ - "model": "auth.permission", - "pk": 146, - "fields": { - "name": "Can act as a referee and submit reports on Submissions", - "content_type": 26, - "codename": "can_referee" - } -}, -{ - "model": "auth.permission", - "pk": 147, - "fields": { - "name": "Can prepare recommendations for voting", - "content_type": 26, - "codename": "can_prepare_recommendations_for_voting" - } -}, -{ - "model": "auth.permission", - "pk": 148, - "fields": { - "name": "Can fix the College voting decision", - "content_type": 26, - "codename": "can_fix_College_decision" - } -}, -{ - "model": "auth.permission", - "pk": 149, - "fields": { - "name": "Can publish accepted submission", - "content_type": 26, - "codename": "can_publish_accepted_submission" - } -} -] diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py index 6e3067a54ec7c406d004e45ebeedbbd14879203a..188cfc787e2c90035a8c035f2b58116452227c70 100644 --- a/scipost/management/commands/add_groups_and_permissions.py +++ b/scipost/management/commands/add_groups_and_permissions.py @@ -38,7 +38,6 @@ class Command(BaseCommand): content_type = ContentType.objects.get_for_model(Contributor) content_type_contact = ContentType.objects.get_for_model(Contact) content_type_draft_invitation = ContentType.objects.get_for_model(DraftInvitation) - content_type_report = ContentType.objects.get_for_model(Report) # Supporting Partners can_manage_SPB, created = Permission.objects.get_or_create( @@ -110,6 +109,10 @@ class Command(BaseCommand): content_type=content_type) # Editorial College + can_manage_college_composition, created = Permission.objects.get_or_create( + codename='can_manage_college_composition', + name='Can manage Editorial College compositions', + content_type=content_type) can_attend_VGMs, created = Permission.objects.get_or_create( codename='can_attend_VGMs', name='Can attend Virtual General Meetings', @@ -153,7 +156,7 @@ class Command(BaseCommand): can_vet_submitted_reports, created = Permission.objects.get_or_create( codename='can_vet_submitted_reports', name='Can vet submitted Reports', - content_type=content_type_report) + content_type=content_type) # Submissions can_submit_manuscript, created = Permission.objects.get_or_create( @@ -304,6 +307,7 @@ class Command(BaseCommand): can_do_plagiarism_checks, can_oversee_refereeing, can_prepare_recommendations_for_voting, + can_manage_college_composition, can_fix_College_decision, can_view_production, can_view_timesheets, diff --git a/scipost/migrations/0043_auto_20170318_2237.py b/scipost/migrations/0043_auto_20170318_2237.py index e8bcfa55845b746bc3b616fc4418fc75af9aed1f..231b06e9922cb3800e82fa7f890217adce67d1d7 100644 --- a/scipost/migrations/0043_auto_20170318_2237.py +++ b/scipost/migrations/0043_auto_20170318_2237.py @@ -4,13 +4,14 @@ from __future__ import unicode_literals from django.db import migrations -from ..db.constants_migration_0043 import collegeMembers +# from ..db.constants_migration_0043 import collegeMembers def fill_editorial_college(apps, schema_editor): EditorialCollege = apps.get_model('scipost', 'EditorialCollege') EditorialMember = apps.get_model('scipost', 'EditorialCollegeMember') college, new = EditorialCollege.objects.get_or_create(discipline='Physics') + collegeMembers = [] for member in collegeMembers: EditorialMember.objects.get_or_create(discipline=college, **member) diff --git a/scipost/mixins.py b/scipost/mixins.py new file mode 100644 index 0000000000000000000000000000000000000000..49dec74f4c44887c0667fbfb9caebf1128e4739b --- /dev/null +++ b/scipost/mixins.py @@ -0,0 +1,15 @@ +from .paginator import SciPostPaginator + + +class PaginationMixin(object): + """ + Mixin for generic class-based views (e.g. django.views.generic.ListView) + """ + paginator_class = SciPostPaginator + + # def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True): + # # Pass the request object to the paginator to keep the parameters in the + # # url querystring ("?page=2&old_param=...") + # request = self.request + # return self.paginator_class(queryset, per_page, orphans=orphans, + # allow_empty_first_page=allow_empty_first_page, request=request) diff --git a/scipost/paginator.py b/scipost/paginator.py new file mode 100644 index 0000000000000000000000000000000000000000..dc253f22e00b765ea1f8fc2b8000417215ad8e0f --- /dev/null +++ b/scipost/paginator.py @@ -0,0 +1,42 @@ +from django.core.paginator import Paginator, Page + +PAGE_RANGE_DISPLAYED = 10 +MARGIN_PAGES_DISPLAYED = 1 +SHOW_FIRST_PAGE_WHEN_INVALID = True + + +class SciPostPaginator(Paginator): + def _get_page(self, *args, **kwargs): + return SciPostPage(*args, **kwargs) + + +class SciPostPage(Page): + def pages(self): + """ + Custom pages set that tweaks the range of pages to be shown in the paginator. + """ + if self.paginator.num_pages <= PAGE_RANGE_DISPLAYED: + return range(1, self.paginator.num_pages + 1) + result = [] + left_side = PAGE_RANGE_DISPLAYED / 2 + right_side = PAGE_RANGE_DISPLAYED - left_side + if self.number > self.paginator.num_pages - PAGE_RANGE_DISPLAYED / 2: + right_side = self.paginator.num_pages - self.number + left_side = PAGE_RANGE_DISPLAYED - right_side + elif self.number < PAGE_RANGE_DISPLAYED / 2: + left_side = self.number + right_side = PAGE_RANGE_DISPLAYED - left_side + for page in range(1, self.paginator.num_pages + 1): + if page <= MARGIN_PAGES_DISPLAYED: + result.append(page) + continue + if page > self.paginator.num_pages - MARGIN_PAGES_DISPLAYED: + result.append(page) + continue + if (page >= self.number - left_side) and (page <= self.number + right_side): + result.append(page) + continue + if result[-1]: + result.append(None) + + return result diff --git a/scipost/static/scipost/assets/css/_alert.scss b/scipost/static/scipost/assets/css/_alert.scss index 6b7a7e21044e48ef372aaaaf4b47731ddcb3f9f8..0e046a8f52e1852e5ed4bfe7ff18ea25108936bf 100644 --- a/scipost/static/scipost/assets/css/_alert.scss +++ b/scipost/static/scipost/assets/css/_alert.scss @@ -14,6 +14,10 @@ &:last-child { margin-bottom: 1rem; } + + p:last-child { + margin-bottom: 0; + } } .alert-dismissible { diff --git a/scipost/static/scipost/assets/css/_list_group.scss b/scipost/static/scipost/assets/css/_list_group.scss index 7387c9c85f91dd41b8e5ec56003f3fc6bcb80099..4755ec289813f41a3be705df5c68db980d203c26 100644 --- a/scipost/static/scipost/assets/css/_list_group.scss +++ b/scipost/static/scipost/assets/css/_list_group.scss @@ -23,9 +23,3 @@ ul.events-list { } } } - -ul[data-target="active-list"] { - li.active { - background-color: $gray-100; - } -} diff --git a/scipost/static/scipost/assets/css/_navbar.scss b/scipost/static/scipost/assets/css/_navbar.scss index 452b2716637529ae319a7b1506839cd1a91581ce..a1ffa8e02c7f39a7152f6c0ff12fa3e724f444cd 100644 --- a/scipost/static/scipost/assets/css/_navbar.scss +++ b/scipost/static/scipost/assets/css/_navbar.scss @@ -95,10 +95,44 @@ .badge { vertical-align: top; - margin-left: -5px; - margin-top: -2px; + margin-left: -15px; + margin-top: -5px; height: 16px; min-width: 16px; - line-height: 12px; + line-height: 10px; + display: none; + padding: 0.25em; + border-radius: 99px; + border: 1px solid #f9f9f9; + } +} + +.notifications_container { + color: $scipost-lightestblue; + + .user { + color: $scipost-darkblue; + } + + .fa { + font-size: 150%; + vertical-align: bottom; + margin: 0 0.25rem; + } + + &.positive_count { + color: $scipost-orange; + + .user { + color: $scipost-darkblue; + } + + .badge { + display: inline-block; + } + } + + &::after { + content: none; } } diff --git a/scipost/static/scipost/assets/css/_pool.scss b/scipost/static/scipost/assets/css/_pool.scss index 1b2ac64b648a293df03462ee9e84fbfc45e227bb..8b6dbdff6d5d38938167dbc50a97e8f29ab90914 100644 --- a/scipost/static/scipost/assets/css/_pool.scss +++ b/scipost/static/scipost/assets/css/_pool.scss @@ -1,39 +1,37 @@ -$pool-icons-width: 40px; -$pool-flex-width: calc(100% - 40px); +.pool-list { + > .submission { + border: 1px solid #ddd; + margin-bottom: 2px; + padding-left: 3rem; + padding-right: 3rem; + position: relative; - -.editorial-admin, -.pool { - .pool-item { .icons { - padding-left: 10px; - padding-right: 10px; - position: relative; - min-height: 1px; - flex: 0 0 $pool-icons-width; - max-width: $pool-icons-width; + max-width: 3rem; + width: 3rem; + position: absolute; + left: 0; + top: 0; + padding: 0.75rem 0.5rem; + text-align: center; } - .item { - flex: 0 0 $pool-flex-width; - width: $pool-flex-width; - max-width: none; + &.active { + border-color: $scipost-darkblue; } } - .card.submission-detail { - position: sticky; - position: -webkit-sticky; - position: -moz-sticky; - position: -ms-sticky; - position: -o-sticky; - top: 15px; - } - - #details .loading { + .loading { position: sticky; top: 15px; padding: 5rem 0 3rem 0; text-align: center; } + + .loading-container { + .submission_title, + .author_list { + display: none; + } + } } diff --git a/scipost/static/scipost/assets/css/_popover.scss b/scipost/static/scipost/assets/css/_popover.scss index 6cc116b60479e5d4661291068b077b55cec1d9c6..5ef240e8b434fe68d4c9fd09f3c5052a61ad69f6 100644 --- a/scipost/static/scipost/assets/css/_popover.scss +++ b/scipost/static/scipost/assets/css/_popover.scss @@ -3,15 +3,53 @@ box-shadow: #ccc 0px 1px 2px 1px; } +.navbar-counter .nav-link:hover { + background-color: $white; +} + +.popover.bs-popover-bottom, +.popover.bs-popover-auto[x-placement^="bottom"] { + .arrow::before { + border-bottom-color: rgb(221, 221, 221); + } + + .arrow::after { + border-bottom-color: #f7f7f7; + } +} + .notifications { + border: 0; + border-radius: 0; + + .popover-header { + font-size: 100%; + padding: 0.3rem 1rem; + font-weight: 600; + text-transform: uppercase; + + a { + color: $scipost-darkblue; + } + } + .popover-body { padding: 0; } &.popover .list-group-item { - padding: 9px 14px; + padding: 0.4rem 1rem; border-radius: 0; border-top: 1px solid #fff; + border-left: 0; + border-right: 0; + flex-direction: row; + justify-content: space-between; + display: flex; + + &:last-child { + border-bottom: 0; + } } .actions { @@ -19,8 +57,12 @@ opacity: 0.0; transition: opacity 0.1s; width: 20px; - float: right; height: 100%; + padding-left: 0.25rem; + + .fa[data-toggle="tooltip"] { + font-size: 1em; + } a:hover { .fa-circle-o:before { diff --git a/scipost/static/scipost/assets/js/notifications.js b/scipost/static/scipost/assets/js/notifications.js index 5900e9eddb03d2e24297916bd10a3a260402d966..49fbe7f24e3f96a1d8a2c82cd9191f42a3f1cfd6 100644 --- a/scipost/static/scipost/assets/js/notifications.js +++ b/scipost/static/scipost/assets/js/notifications.js @@ -1,3 +1,4 @@ +var notify_container_class = "notifications_container"; var notify_badge_class = "live_notify_badge"; var notify_menu_class = "live_notify_list"; var notify_api_url_count = "/notifications/api/unread_count/"; @@ -15,10 +16,10 @@ function initiate_popover(reinitiate) { reinitiate = false; } - var notification_template = '<div class="popover notifications" role="tooltip"><div class="arrow"></div><h3 class="popover-header h2"></h3><div class="popover-body"></div></div>'; + var notification_template = '<div class="popover notifications" role="tooltip"><div class="arrow"></div><p class="popover-header"></p><div class="popover-body"></div></div>'; function get_notifications_title() { - return 'Latest notifications <div class="badge badge-warning badge-pill live_notify_badge"></div><div class="mt-1"><small><a href="/notifications">See all my notifications</a> · <a href="javascript:;" class="mark_all_read">Mark all as read</a></small></div>'; + return 'My inbox'; } function get_notifications() { @@ -83,9 +84,15 @@ function mark_toggle(el) { function fill_notification_badge(data) { var badges = document.getElementsByClassName(notify_badge_class); + var container = $('.' + notify_container_class); if (badges) { for(var i = 0; i < badges.length; i++){ badges[i].innerHTML = data.unread_count; + if (data.unread_count > 0) { + container.addClass('positive_count'); + } else { + container.removeClass('positive_count'); + } } } } @@ -94,7 +101,7 @@ function get_notification_list() { fetch_api_data(notify_api_url_list, true, function(data) { var messages = data.list.map(function (item) { - var message = ''; + var message = "<div>"; if(typeof item.actor !== 'undefined'){ message += '<strong>' + item.actor + '</strong>'; } @@ -109,15 +116,16 @@ function get_notification_list() { } } if(typeof item.timesince !== 'undefined'){ - message += " <div class='text-muted'>" + item.timesince + " ago</div>"; + message += "<br><small class='text-muted'>" + item.timesince + " ago</small>"; } + message += "</div>"; if(item.unread) { var mark_as_read = '<div class="actions"><a href="javascript:;" data-slug="' + item.slug + '"><i class="fa fa-circle" data-toggle="tooltip" data-placement="auto" title="Mark as read" aria-hidden="true"></i></a></div>'; } else { var mark_as_read = '<div class="actions"><a href="javascript:;" data-slug="' + item.slug + '"><i class="fa fa-circle-o" data-toggle="tooltip" data-placement="auto" title="Mark as unread" aria-hidden="true"></i></a></div>'; } - return '<li class="list-group-item ' + (item.unread ? ' active' : '') + '">' + mark_as_read + message + '</li>'; + return '<li class="list-group-item ' + (item.unread ? ' active' : '') + '">' + message + mark_as_read + '</li>'; }).join(''); if (messages == '') { diff --git a/scipost/static/scipost/assets/js/scripts.js b/scipost/static/scipost/assets/js/scripts.js index 35883ec42ba87948933db9c2d3973914f7b41b2a..d3478c7210700de698ea232ae6c0ef3f30c63a50 100644 --- a/scipost/static/scipost/assets/js/scripts.js +++ b/scipost/static/scipost/assets/js/scripts.js @@ -28,7 +28,6 @@ var getUrlParameter = function getUrlParameter(sParam) { }; function init_page() { - console.log('init!') // Show right tab if url contains `tab` GET request var tab = getUrlParameter('tab') if (tab) { @@ -45,6 +44,14 @@ function init_page() { $($(this).attr('data-target')).toggle(); }); + // Make links that could possibly hide html blocks + $('[data-toggle="hide"]').on('click', function() { + $($(this).attr('data-target')) + .hide() + .parents('.active') + .removeClass('active'); + }); + activate_tooltip(); } @@ -66,12 +73,12 @@ $(function(){ var self = this, url = $(this).attr('href'), target = $(this).attr('data-target'); - // console.log('click', url, target); - $(target).html('<div class="loading"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>'); + $(target) + .show() + .html('<div class="loading"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i></div>'); $.get(url + '?json=1').done(function(data) { - // console.log('done', data); $(target).html(data).promise().done(function() { init_page(); }); diff --git a/scipost/templates/scipost/Fellow_activity_overview.html b/scipost/templates/scipost/Fellow_activity_overview.html index e0515b48661fb8c87c7b2ca09f9a77260b286238..dcfe8de994c2eb99145f8c0818d843ee436aa427 100644 --- a/scipost/templates/scipost/Fellow_activity_overview.html +++ b/scipost/templates/scipost/Fellow_activity_overview.html @@ -19,10 +19,9 @@ </div> </div> -<div class="row"> - <div class="col-12"> - <table class="assignments_listing w-100"> - <thead> +<table class="assignments_listing w-100"> + <thead class=""> + <tr> <th>Name</th> <th>Expertises</th> <th>Ongoing</th> @@ -31,20 +30,19 @@ <th>Refused<br/>last yr / tot</th> <th>Ignored<br/>last yr / tot</th> <th>Fulfilled<br/>last yr / tot</th> - </thead> - <tbody> - {% for fellow in fellows %} - <tr> - <td> - <a href="{% url 'scipost:Fellow_activity_overview' %}?fellow={{fellow.id}}">{{ fellow.user.last_name }}, {{ fellow.user.first_name }}</a> - </td> - {% include 'partials/scipost/contributor_assignments_as_td.html' with contributor=fellow %} - </tr> - {% endfor %} - </tbody> - </table> - </div> -</div> + </tr> + </thead> + <tbody> + {% for fellow in fellows %} + <tr> + <td> + <a href="{% url 'scipost:Fellow_activity_overview' %}?fellow={{fellow.id}}">{{ fellow.user.last_name }}, {{ fellow.user.first_name }}</a> + </td> + {% include 'partials/scipost/contributor_assignments_as_td.html' with contributor=fellow %} + </tr> + {% endfor %} + </tbody> +</table> {% if fellow %} <div class="row"> @@ -61,7 +59,10 @@ <ul class="list-group list-group-flush"> {% for assignment in assignments_ongoing %} <li class="list-group-item"> - {% include 'submissions/_submission_card_contributor_content.html' with submission=assignment.submission %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=assignment.submission %} + {% include 'submissions/_submission_status_block.html' with submission=assignment.submission %} + </div> </li> {% empty %} <li class="list-group-item">No completed assignments</li> @@ -77,7 +78,10 @@ <ul class="list-group list-group-flush"> {% for assignment in assignments_completed %} <li class="list-group-item"> - {% include 'submissions/_submission_card_contributor_content.html' with submission=assignment.submission %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=assignment.submission %} + {% include 'submissions/_submission_status_block.html' with submission=assignment.submission %} + </div> </li> {% empty %} <li class="list-group-item">No completed assignments</li> diff --git a/scipost/templates/scipost/_public_info_as_table.html b/scipost/templates/scipost/_public_info_as_table.html index 964e8098875162e47bc4b1fa7a16f1687b1b29cf..e41461ee178b3bdd9e01b9b0ba92804abf6b04ca 100644 --- a/scipost/templates/scipost/_public_info_as_table.html +++ b/scipost/templates/scipost/_public_info_as_table.html @@ -2,9 +2,8 @@ <tr><td>Title: </td><td> </td><td>{{ contributor.get_title_display }}</td></tr> <tr><td>First name: </td><td> </td><td>{{ contributor.user.first_name }}</td></tr> <tr><td>Last name: </td><td> </td><td>{{ contributor.user.last_name }}</td></tr> - <tr><td>ORCID id: </td><td> </td><td>{{ contributor.orcid_id }}</td></tr> - <tr><td>Country of employment: </td><td> </td> - <td>{{ contributor.country_of_employment.name }}</td></tr> - <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation }}</td></tr> - <tr><td>Personal web page: </td><td> </td><td>{{ contributor.personalwebpage }}</td></tr> + <tr><td>ORCID id: </td><td> </td><td>{{ contributor.orcid_id|default:'-' }}</td></tr> + <tr><td>Country of employment: </td><td> </td><td>{{ contributor.country_of_employment.name|default:'-'}}</td></tr> + <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation|default:'-' }}</td></tr> + <tr><td>Personal web page: </td><td> </td><td>{{ contributor.personalwebpage|default:'-' }}</td></tr> </table> diff --git a/scipost/templates/scipost/claim_authorships.html b/scipost/templates/scipost/claim_authorships.html index 8a774d4378e36742c6786cc783f4678f543d93c6..7a5144847a5e021d1f5abf766eada6fa3525dba7 100644 --- a/scipost/templates/scipost/claim_authorships.html +++ b/scipost/templates/scipost/claim_authorships.html @@ -58,7 +58,7 @@ <div class="col-12"> {% for sub in submission_authorships_to_claim %} <div class="card"> - {% include 'submissions/_submission_card_content.html' with submission=sub %} + {% include 'partials/submissions/submission_card_content.html' with submission=sub %} <div class="card-footer"> <form class="d-inline-block" action="{% url 'scipost:claim_sub_authorship' submission_id=sub.id claim=1 %}" method="post"> {% csrf_token %} diff --git a/scipost/templates/scipost/contributor_info.html b/scipost/templates/scipost/contributor_info.html index f97fa477386456fd5faf5ea437fee782e89043f8..7ee2c8988a5f5d791b97c4ff50740fd03d0968cf 100644 --- a/scipost/templates/scipost/contributor_info.html +++ b/scipost/templates/scipost/contributor_info.html @@ -37,7 +37,6 @@ {% endif %} {% if contributor_submissions %} - {# <hr>#} <div class="row"> <div class="col-12"> <h2 class="highlight">Submissions <small><a href="javascript:;" class="ml-2" data-toggle="toggle" data-target="#mysubmissionslist">View/hide submissions</a></small></h2> @@ -48,7 +47,9 @@ <ul class="list-group list-group-flush"> {% for sub in contributor_submissions %} <li class="list-group-item"> - {% include 'submissions/_submission_card_content.html' with submission=sub %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=sub %} + </div> </li> {% endfor %} </ul> diff --git a/scipost/templates/scipost/index.html b/scipost/templates/scipost/index.html index c5cc4d3b4c455618213d1fcdd9b1ac2e854e049e..36cd4a79dc0af6b6ad7844469e2327b0bf9d26b1 100644 --- a/scipost/templates/scipost/index.html +++ b/scipost/templates/scipost/index.html @@ -59,7 +59,9 @@ <ul class="list-group list-group-flush"> {% for submission in submissions %} <li class="list-group-item"> - {% include 'submissions/_submission_card_content_sparse.html' with submission=submission %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content_homepage.html' with submission=submission %} + </div> </li> {% endfor %} <li class="list-group-item"> diff --git a/scipost/templates/scipost/navbar.html b/scipost/templates/scipost/navbar.html index ef66e3d109922ea8d862d26fffecbbd32430eb0c..93ccffea2081b2623fabd849169e3cf6546e36a8 100644 --- a/scipost/templates/scipost/navbar.html +++ b/scipost/templates/scipost/navbar.html @@ -29,9 +29,9 @@ {% if request.user|is_in_group:'Testers' %} <li class="nav-item highlighted dropdown navbar-counter"> <div class="nav-link"> - <span class="user">{% if user.last_name %}{% if user.contributor %}{{ user.contributor.get_title_display }} {% endif %}{{ user.first_name }} {{ user.last_name }}{% else %}{{ user.username }}{% endif %}</span> - <a href="javascript:;" class="d-inline-block ml-1 dropdown-toggle" id="notifications_badge"> - <i class="fa fa-bell-o" aria-hidden="true"></i> + <a href="javascript:;" class="d-inline-block ml-1 dropdown-toggle notifications_container" id="notifications_badge"> + <span class="user">{% if user.last_name %}{% if user.contributor %}{{ user.contributor.get_title_display }} {% endif %}{{ user.first_name }} {{ user.last_name }}{% else %}{{ user.username }}{% endif %}</span> + <i class="fa fa-inbox" aria-hidden="true"></i> {% live_notify_badge classes="badge badge-pill badge-primary" %} </a> {% live_notify_list classes="update_notifications d-none" %} diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index df6434f83530092e5f3ad28a0e65b77f61e91af5..19522be6222256824b92c3703e6088d23d5ef881 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -1,6 +1,7 @@ {% extends 'scipost/base.html' %} {% load bootstrap %} +{% load user_groups %} {% block pagetitle %}: personal page{% endblock pagetitle %} @@ -17,6 +18,17 @@ </div> {% else %} + {# Save all Permission groups into template variables #} + {% is_edcol_admin request.user as is_edcol_admin %} + {% is_scipost_admin request.user as is_scipost_admin %} + {% is_editorial_college request.user as is_editorial_college %} + {% is_advisory_board request.user as is_advisory_board %} + {% is_vetting_editor request.user as is_vetting_editor %} + {% is_ambassador request.user as is_ambassador %} + {% is_junior_ambassador request.user as is_junior_ambassador %} + {% is_registered_contributor request.user as is_registered_contributor %} + {% is_tester request.user as is_tester %} + {% is_production_officer request.user as is_production_officer %} <div class="row"> <div class="col-12"> @@ -33,7 +45,7 @@ <li class="nav-item btn btn-secondary"> <a href="#account" class="nav-link active" data-toggle="tab">Account</a> </li> - {% if 'SciPost Administrators' in user_groups or 'Editorial Administrators' in user_groups or 'Editorial College' in user_groups or 'Advisory Board' in user_groups or 'Vetting Editors' in user_groups or 'Ambassadors' in user_groups or 'Junior Ambassadors' in user_groups %} + {% if is_scipost_admin or is_edcol_admin or is_editorial_college or is_advisory_board or is_vetting_editor or is_ambassador or is_junior_ambassador %} <li class="nav-item btn btn-secondary"> <a href="#editorial-actions" class="nav-link" data-toggle="tab">Editorial Actions</a> </li> @@ -110,13 +122,13 @@ </div> <div class="col-md-6"> {% if contributor %} - {# Scientist fields #} - {% if not contributor.is_currently_available %} - <h3 class="text-warning">You are currently unavailable</h3> - <p>Check your availability underneath if this should not be the case.</p> - <hr> - {% endif %} - {# END: Scientist fields #} + {# Scientist fields #} + {% if not contributor.is_currently_available %} + <h3 class="text-warning">You are currently unavailable</h3> + <p>Check your availability underneath if this should not be the case.</p> + <hr> + {% endif %} + {# END: Scientist fields #} {% endif %} {% if not request.user.contributor.petition_signatories.exists %} @@ -124,40 +136,75 @@ <h3 class="text-danger">Scientists, please help us out!</h3> <p class="mb-1">If it is not listed on our Partners page, please encourage your institution (through a librarian, director, ...) to join by <a class="h3 text-blue" href="{% url 'petitions:petition' slug='join-SPB' %}">signing our petition</a>.</p> </div> + <hr> {% endif %} - <hr> - {% if 'SciPost Administrators' in user_groups %} + {% if is_scipost_admin %} <h3>You are a SciPost Administrator.</h3> {% endif %} - {% if 'Editorial Administrators' in user_groups %} + {% if is_edcol_admin %} <h3>You are a SciPost Editorial Administrator.</h3> {% endif %} - {% if 'Advisory Board' in user_groups %} + {% if is_advisory_board %} <h3>You are a member of the Advisory Board.</h3> {% endif %} - {% if 'Editorial College' in user_groups %} + {% if is_editorial_college %} <h3>You are a member of the Editorial College.</h3> {% endif %} - {% if 'Vetting Editors' in user_groups %} + {% if is_vetting_editor %} <h3>You are a SciPost Vetting Editor.</h3> {% endif %} - {% if 'Registered Contributors' in user_groups %} + {% if is_registered_contributor %} <h3>You are a Registered Contributor.</h3> {% endif %} - {% if 'Testers' in user_groups %} + {% if is_tester %} <h3>You are a SciPost Tester.</h3> {% endif %} - {% if 'Ambassadors' in user_groups %} + {% if is_ambassador %} <h3>You are a SciPost Ambassador.</h3> {% endif %} - {% if 'Junior Ambassadors' in user_groups %} + {% if is_junior_ambassador %} <h3>You are a SciPost Junior Ambassador.</h3> {% endif %} - {% if 'Production Officers' in user_groups %} + {% if is_production_officer %} <h3>You are a SciPost Production Officer.</h3> {% endif %} + {% if contributor.fellowships.exists %} + <h3>Your Fellowships:</h3> + <ul class="mb-2"> + {% for fellowship in contributor.fellowships.all %} + <li class="pt-1"> + {{ fellowship.contributor.get_discipline_display }} + + {% if fellowship.guest %} + (Guest Fellowship) + {% else %} + (Regular Fellowship) + {% endif %} + + {% if not fellowship.is_active %} + <span class="label label-outline-warning label-sm">Inactive</span> + {% endif %} + + {% if fellowship.start_date or fellowship.until_date %} + <div class="text-muted"> + {% if fellowship.start_date %} + from {{ fellowship.start_date }} + {% endif %} + + {% if fellowship.until_date %} + until {{ fellowship.until_date }} + {% endif %} + </div> + {% endif %} + </li> + + {% endfor %} + </ul> + <a href="{% url 'submissions:pool' %}" class="h3 text-primary ml-4 px-3 d-block-inline">Go to the Submissions Pool</a> + {% endif %} + <h3 class="mt-3">Update your personal data or password</h3> <ul> @@ -214,7 +261,7 @@ {% endif %} </div><!-- End tab --> - {% if 'SciPost Administrators' in user_groups or 'Editorial Administrators' in user_groups or 'Editorial College' in user_groups or 'Advisory Board' in user_groups or 'Vetting Editors' in user_groups or 'Ambassadors' in user_groups or 'Junior Ambassadors' in user_groups %} + {% if is_scipost_admin or is_edcol_admin or is_editorial_college or is_advisory_board or is_vetting_editor or is_ambassador or is_junior_ambassador %} <!-- Tab: Editorial Actions --> <div class="tab-pane" id="editorial-actions" role="tabpanel"> <div class="row"> @@ -228,7 +275,7 @@ </div> <div class="row"> - {% if 'SciPost Administrators' in user_groups or 'Advisory Board' in user_groups or 'Ambassadors' in user_groups or 'Junior Ambassadors' in user_groups %} + {% if is_scipost_admin or is_advisory_board or is_ambassador or is_junior_ambassador %} <div class="col-md-4"> <h3>Registration actions</h3> <ul> @@ -253,7 +300,7 @@ </ul> {% endif %} - {% if 'SciPost Administrators' in user_groups %} + {% if is_scipost_admin %} <h3>Email communications</h3> <ul> {% if perms.scipost.can_email_group_members %} @@ -279,7 +326,7 @@ {% endif %} <div class="col-md-4"> - {% if 'Vetting Editors' in user_groups or perms.scipost.can_vet_submitted_reports %} + {% if is_vetting_editor or perms.scipost.can_vet_submitted_reports %} <h3>Vetting actions</h3> <ul> {% if perms.scipost.can_vet_commentary_requests %} @@ -300,7 +347,7 @@ </ul> {% endif %} - {% if 'Editorial Administrators' in user_groups %} + {% if is_edcol_admin %} <h3>Editorial Admin actions</h3> <ul> <li><a href="{% url 'submissions:reports_accepted_list' %}">Accepted Reports</a>{% if nr_reports_without_pdf %} ({{nr_reports_without_pdf}} unfinished){% endif %}</li> @@ -310,6 +357,8 @@ <li><a href="{% url 'journals:manage_metadata' %}">Manage Publication metadata</a></li> <li><a href="{% url 'journals:manage_report_metadata' %}">Manage Report metadata</a></li> <li><a href="{% url 'journals:manage_comment_metadata' %}">Manage Comment metadata</a></li> + <li><a href="{% url 'colleges:fellowships' %}">Manage Fellowships</a></li> + <li><a href="{% url 'proceedings:proceedings' %}">Manage Proceedings Issues</a></li> </ul> {% endif %} @@ -321,7 +370,7 @@ {% endif %} </div> - {% if 'Editorial Administrators' in user_groups or 'Editorial College' in user_groups %} + {% if is_edcol_admin or is_editorial_college %} <div class="col-md-4"> <h3>Info</h3> <ul> @@ -342,16 +391,16 @@ {% endif %} </ul> - {% if 'Editorial Administrators' in user_groups %} - <h3>Refereeing overview</h3> - <ul> - <li>View (and act on) outstanding refereeing invitations in the <a href="{% url 'submissions:refereeing_overview' %}">refereeing overview</a></li> - <li><a href="{% url 'stats:statistics' %}">View statistics</a> for submissions, refereeing, publishing</li> - </ul> - <h3>Voting</h3> - <ul> - <li>Prepare Editorial Recommendations for voting via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_recommendations_to_prepare_for_voting }})</li> - </ul> + {% if is_edcol_admin %} + <h3>Refereeing overview</h3> + <ul> + <li>View (and act on) outstanding refereeing invitations in the <a href="{% url 'submissions:refereeing_overview' %}">refereeing overview</a></li> + <li><a href="{% url 'stats:statistics' %}">View statistics</a> for submissions, refereeing, publishing</li> + </ul> + <h3>Voting</h3> + <ul> + <li>Prepare Editorial Recommendations for voting via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_recommendations_to_prepare_for_voting }})</li> + </ul> {% endif %} </div> {% endif %} @@ -366,7 +415,11 @@ <ul class="list-group list-group-flush"> {% for assignment in active_assignments %} <li class="list-group-item"> - {% include 'submissions/_submission_card_eic_content.html' with submission=assignment.submission %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=assignment.submission %} + {% include 'submissions/_submission_status_block.html' with submission=assignment.submission %} + <p class="card-text mt-2">Manage this Submission from its <a href="{% url 'submissions:editorial_page' assignment.submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a>.</p> + </div> </li> {% endfor %} </ul> @@ -444,7 +497,9 @@ <ul class="list-group list-group-flush"> {% for task in pending_ref_tasks %} <li class="list-group-item"> - {% include 'submissions/_refereeing_invitation_card_content.html' with invitation=task %} + <div class="card-body px-0"> + {% include 'partials/submissions/refereeing_invitation_card_content.html' with invitation=task %} + </div> </li> {% empty %} <li class="list-group-item"><em>You do not have any pending refereeing task</em></li> @@ -462,8 +517,10 @@ <ul class="list-group list-group-flush"> {% for report in contributor.reports.in_draft.all %} <li class="list-group-item"> - <div class="w-100">{% include 'submissions/_submission_card_content.html' with submission=report.submission %}</div> - <div class="px-2 mb-2"><a class="px-1" href="{% url 'submissions:submit_report' report.submission.arxiv_identifier_w_vn_nr %}">Finish report</a></div> + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=report.submission %} + <a class="btn btn-outline-primary my-2" href="{% url 'submissions:submit_report' report.submission.arxiv_identifier_w_vn_nr %}">Finish report</a> + </div> </li> {% endfor %} </ul> @@ -483,7 +540,7 @@ {% comment %} Temporary: There is already a template for a "Report summary" in a parallel (unmerged) branch. Awaiting merge to use that template. {% endcomment %} - <div class="card-body {% block cardblock_class_block %}{% endblock %}"> + <div class="card-body px-0 {% block cardblock_class_block %}{% endblock %}"> <h3>Report on Submission <a href="{{report.submission.get_absolute_url}}">{{report.submission.title}}</a></h3> <table> <tr> @@ -537,7 +594,21 @@ <ul class="list-group list-group-flush"> {% for sub in own_submissions %} <li class="list-group-item"> - {% include 'submissions/_submission_card_author_content.html' with submission=sub current_user=request.user %} + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=sub %} + {% include 'submissions/_submission_status_block.html' with submission=sub %} + + {% if request.user.contributor == sub.submitted_by %} + <p class="card-text mt-1"> + {% if sub.editor_in_charge %} + <a href="{% url 'submissions:communication' sub.arxiv_identifier_w_vn_nr 'AtoE' %}">Write to the Editor-in-charge</a> + {% endif %} + {% if sub.status == 'revision_requested' %} + · <a href="{% url 'submissions:prefill_using_identifier' %}?identifier={{ sub.arxiv_identifier_wo_vn_nr }}">Resubmit this manuscript</a> + {% endif %} + </p> + {% endif %} + </div> </li> {% empty %} <li class="list-group-item"> diff --git a/scipost/templates/scipost/vet_authorship_claims.html b/scipost/templates/scipost/vet_authorship_claims.html index 54711cdaa79a973b44afc7c8b825d5830167b1e0..fb805bc4c09ce55ad6a0f68dfb544939d922117f 100644 --- a/scipost/templates/scipost/vet_authorship_claims.html +++ b/scipost/templates/scipost/vet_authorship_claims.html @@ -26,16 +26,12 @@ </div> {% else %} -<div class="row"> - <div class="col-12"> - <h1 class="highlight">Vet Authorship Claims</h1> - </div> -</div> +<h1 class="highlight">Vet Authorship Claims</h1> - <ul class="list-group list-group-flush"> + {# <ul class="list-group list-group-flush">#} {% for claim in claims_to_vet %} - <li class="list-unstyled"> - <div class="card w-100"> + {# <li class="list-group-item">#} + <div class="card "> {% if claim.publication %} <div class="card-header"> <h4>Contributor {{ claim.claimant.user.first_name }} {{ claim.claimant.user.last_name }} claims to be an author of Publication:</h4> @@ -45,7 +41,9 @@ <div class="card-header"> <h4>Contributor {{ claim.claimant.user.first_name }} {{ claim.claimant.user.last_name }} claims to be an author of Submission:</h4> </div> - {% include 'submissions/_submission_card_content.html' with submission=claim.submission %} + <div class="card-body"> + {% include 'partials/submissions/submission_card_content.html' with submission=claim.submission %} + </div> {% elif claim.commentary %} <div class="card-header"> <h4>Contributor {{ claim.claimant.user.first_name }} {{ claim.claimant.user.last_name }} claims to be an author of Commentary:</h4> @@ -60,17 +58,17 @@ <div class="card-footer"> <form class="d-inline-block" action="{% url 'scipost:vet_authorship_claim' claim_id=claim.id claim=1%}" method="post"> {% csrf_token %} - <input class="btn btn-secondary" type="submit" value="Accept" /> + <input class="btn btn-secondary px-3" type="submit" value="Accept" /> </form> <form class="d-inline-block ml-1" action="{% url 'scipost:vet_authorship_claim' claim_id=claim.id claim=0%}" method="post"> {% csrf_token %} - <input class="btn btn-danger" type="submit" value="Deny" /> + <input class="btn btn-danger px-3" type="submit" value="Deny" /> </form> </div> </div> - </li> + {# </li>#} {% endfor %} - </ul> + {# </ul>#} {% endif %} diff --git a/scipost/templatetags/user_groups.py b/scipost/templatetags/user_groups.py index 408837b3610ed36499ad4a021c0c8124ccecf6c2..21a1f0ff5f5db9656c5c2a68cfec6eb6641bb5eb 100644 --- a/scipost/templatetags/user_groups.py +++ b/scipost/templatetags/user_groups.py @@ -10,3 +10,105 @@ def is_edcol_admin(user): This assignment is limited to a certain context block! """ return user.groups.filter(name='Editorial Administrators').exists() or user.is_superuser + + +@register.simple_tag +def is_scipost_admin(user): + """ + Assign template variable (boolean) to check if user is SciPost Administrator. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='SciPost Administrators').exists() or user.is_superuser + + +@register.simple_tag +def is_editorial_college(user): + """ + Assign template variable (boolean) to check if user is member of Editorial College group. + + !!! + This filter should actually be dynamic, not checking the permissions group but the current + active Fellowship instances for the user. + !!! + + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Editorial College').exists() or user.is_superuser + + +@register.simple_tag +def is_advisory_board(user): + """ + Assign template variable (boolean) to check if user is in Advisory Board. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Advisory Board').exists() or user.is_superuser + + +@register.simple_tag +def is_vetting_editor(user): + """ + Assign template variable (boolean) to check if user is in Vetting Editor. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Vetting Editors').exists() or user.is_superuser + + +@register.simple_tag +def is_ambassador(user): + """ + Assign template variable (boolean) to check if user is Ambassador. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Ambassadors').exists() or user.is_superuser + + +@register.simple_tag +def is_junior_ambassador(user): + """ + Assign template variable (boolean) to check if user is Junior Ambassador. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Junior Ambassadors').exists() or user.is_superuser + + +@register.simple_tag +def is_registered_contributor(user): + """ + Assign template variable (boolean) to check if user is Registered Contributor. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Registered Contributors').exists() or user.is_superuser + + +@register.simple_tag +def is_tester(user): + """ + Assign template variable (boolean) to check if user is Tester. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Testers').exists() or user.is_superuser + + +@register.simple_tag +def is_production_officer(user): + """ + Assign template variable (boolean) to check if user is Production Officer. + This assignment is limited to a certain context block! + """ + return user.groups.filter(name='Production Officers').exists() or user.is_superuser + + +@register.simple_tag +def is_editor_in_charge(user, submission): + """ + Assign template variable (boolean) to check if user is Editorial Administator. + This assignment is limited to a certain context block! + """ + if user.is_superuser: + return True + + if not hasattr(user, 'contributor'): + return False + + return submission.editor_in_charge == user.contributor diff --git a/scipost/views.py b/scipost/views.py index fb5ff5b6cf000087a8bf638593772d59fea71478..9b222806a95855071b71a348e0b44614e44c1699 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -719,7 +719,6 @@ def personal_page(request): context['needs_validation'] = contributor.status != CONTRIBUTOR_NORMAL except Contributor.DoesNotExist: contributor = None - context['user_groups'] = request.user.groups.values_list('name', flat=True) if contributor: # Compile the unavailability periods: diff --git a/submissions/admin.py b/submissions/admin.py index 252b1d19bf854f93693cce13743ce505c905c48e..8a2f0f0e8b2c17c38316d4457694c62ba59aa519 100644 --- a/submissions/admin.py +++ b/submissions/admin.py @@ -86,7 +86,8 @@ class SubmissionAdmin(GuardedModelAdmin): 'discipline', 'domain', 'subject_area', - 'secondary_areas'), + 'secondary_areas', + 'proceedings'), }), ('Authors', { 'classes': ('collapse',), @@ -110,8 +111,10 @@ class SubmissionAdmin(GuardedModelAdmin): 'referees_suggested', 'remarks_for_editors', 'submitted_to_journal', + 'proceedings', 'pdf_refereeing_pack', - 'plagiarism_report'), + 'plagiarism_report', + 'fellows'), }), ('Meta', { 'classes': ('collapse',), diff --git a/submissions/forms.py b/submissions/forms.py index ef88d0341896ece923b8c7d75697eaea8b29d8a9..e3f25ca00d3876b6638dae59aeefa276b044b7fc 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -2,12 +2,9 @@ import re from django import forms from django.conf import settings -from django.contrib.auth.models import Group from django.db import transaction from django.utils import timezone -from guardian.shortcuts import assign_perm - from .constants import ASSIGNMENT_BOOL, ASSIGNMENT_REFUSAL_REASONS, STATUS_RESUBMITTED,\ REPORT_ACTION_CHOICES, REPORT_REFUSAL_CHOICES, STATUS_REVISION_REQUESTED,\ STATUS_REJECTED, STATUS_REJECTED_VISIBLE, STATUS_RESUBMISSION_INCOMING,\ @@ -17,6 +14,8 @@ from . import exceptions, helpers from .models import Submission, RefereeInvitation, Report, EICRecommendation, EditorialAssignment,\ iThenticateReport +from colleges.models import Fellowship +from journals.constants import SCIPOST_JOURNAL_PHYSICS_PROC from scipost.constants import SCIPOST_SUBJECT_AREAS from scipost.services import ArxivCaller from scipost.models import Contributor @@ -43,19 +42,30 @@ class SubmissionSearchForm(forms.Form): class SubmissionPoolFilterForm(forms.Form): - status = forms.ChoiceField(choices=((None, 'All statuses'),) + SUBMISSION_STATUS, - required=False) - editor_in_charge = forms.BooleanField(label='Show only Submissions for which I am editor in charge.', required=False) + status = forms.ChoiceField( + choices=((None, 'All submissions currently under evaluation'),) + SUBMISSION_STATUS, + required=False) + editor_in_charge = forms.BooleanField( + label='Show only Submissions for which I am editor in charge.', required=False) - def search(self, queryset, current_contributor=None): + def search(self, queryset, current_user): if self.cleaned_data.get('status'): # Do extra check on non-required field to never show errors on template - queryset = queryset.filter(status=self.cleaned_data['status']) + queryset = queryset.pool_full(current_user).filter(status=self.cleaned_data['status']) + else: + # If no specific status if requested, just return the Pool by default + queryset = queryset.pool(current_user) + + if self.cleaned_data.get('editor_in_charge') and hasattr(current_user, 'contributor'): + queryset = queryset.filter(editor_in_charge=current_user.contributor) - if self.cleaned_data.get('editor_in_charge') and current_contributor: - queryset = queryset.filter(editor_in_charge=current_contributor) + return queryset.order_by('-submission_date') - return queryset + def status_verbose(self): + try: + return dict(SUBMISSION_STATUS)[self.cleaned_data['status']] + except KeyError: + return '' ############################### @@ -222,6 +232,7 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): 'is_resubmission', 'discipline', 'submitted_to_journal', + 'proceedings', 'submission_type', 'domain', 'subject_area', @@ -256,6 +267,19 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): self.fields['list_of_changes'].widget.attrs.update({ 'placeholder': 'Give a point-by-point list of changes (will be viewable online)'}) + # Proceedings submission + qs = self.fields['proceedings'].queryset.open_for_submission() + self.fields['proceedings'].queryset = qs + self.fields['proceedings'].empty_label = None + if not qs.exists(): + # Open the proceedings Journal for submission + def filter_proceedings(item): + return item[0] != SCIPOST_JOURNAL_PHYSICS_PROC + + self.fields['submitted_to_journal'].choices = filter( + filter_proceedings, self.fields['submitted_to_journal'].choices) + del self.fields['proceedings'] + # Update placeholder for the other fields self.fields['arxiv_link'].widget.attrs.update({ 'placeholder': 'ex.: arxiv.org/abs/1234.56789v1'}) @@ -278,6 +302,10 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): self.do_pre_checks(cleaned_data['arxiv_identifier_w_vn_nr']) self.arxiv_meets_regex(cleaned_data['arxiv_identifier_w_vn_nr'], cleaned_data['submitted_to_journal']) + + if self.cleaned_data['submitted_to_journal'] != SCIPOST_JOURNAL_PHYSICS_PROC: + del self.cleaned_data['proceedings'] + return cleaned_data def clean_author_list(self): @@ -327,11 +355,6 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): @transaction.atomic def reassign_eic_and_admins(self, submission): - # Assign permissions - 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) - # Assign editor assignment = EditorialAssignment( submission=submission, @@ -342,6 +365,18 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): submission.save() return submission + def set_pool(self, submission): + qs = Fellowship.objects.active() + fellows = qs.regular().filter( + contributor__discipline=submission.discipline).return_active_for_submission(submission) + submission.fellows.set(fellows) + + if submission.proceedings: + # Add Guest Fellowships if the Submission is a Proceedings manuscript + guest_fellows = qs.guests().filter( + proceedings=submission.proceedings).return_active_for_submission(submission) + submission.fellows.add(*guest_fellows) + @transaction.atomic def save(self): """ @@ -368,6 +403,7 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): submission = self.copy_and_save_data_from_resubmission(submission) submission = self.reassign_eic_and_admins(submission) submission.authors.add(self.requested_by.contributor) + self.set_pool(submission) return submission @@ -434,21 +470,37 @@ class SetRefereeingDeadlineForm(forms.Form): return self.cleaned_data.get('deadline') -class VotingEligibilityForm(forms.Form): +class VotingEligibilityForm(forms.ModelForm): + eligible_fellows = forms.ModelMultipleChoiceField( + queryset=Contributor.objects.none(), + widget=forms.CheckboxSelectMultiple({'checked': 'checked'}), + required=True, label='Eligible for voting') + + class Meta: + model = EICRecommendation + fields = () def __init__(self, *args, **kwargs): - discipline = kwargs.pop('discipline') - subject_area = kwargs.pop('subject_area') - super(VotingEligibilityForm, self).__init__(*args, **kwargs) - self.fields['eligible_Fellows'] = forms.ModelMultipleChoiceField( - queryset=Contributor.objects.filter( - user__groups__name__in=['Editorial College'], - user__contributor__discipline=discipline, - user__contributor__expertises__contains=[subject_area] - ).order_by('user__last_name'), - widget=forms.CheckboxSelectMultiple({'checked': 'checked'}), - required=True, label='Eligible for voting', - ) + super().__init__(*args, **kwargs) + # Do we need this discipline filter still with the new Pool construction??? + # -- JdW; Oct 20th, 2017 + self.fields['eligible_fellows'].queryset = Contributor.objects.filter( + fellowships__pool=self.instance.submission, + discipline=self.instance.submission.discipline, + expertises__contains=[self.instance.submission.subject_area] + ).order_by('user__last_name') + + def save(self, commit=True): + recommendation = self.instance + recommendation.eligible_to_vote = self.cleaned_data['eligible_fellows'] + submission = self.instance.submission + submission.status = 'put_to_EC_voting' + + if commit: + recommendation.save() + submission.save() + recommendation.voted_for.add(recommendation.submission.editor_in_charge) + return recommendation ############ @@ -616,12 +668,15 @@ class EditorialCommunicationForm(forms.Form): class EICRecommendationForm(forms.ModelForm): class Meta: model = EICRecommendation - fields = ['recommendation', - 'remarks_for_authors', 'requested_changes', - 'remarks_for_editorial_college'] + fields = [ + 'recommendation', + 'remarks_for_authors', + 'requested_changes', + 'remarks_for_editorial_college' + ] def __init__(self, *args, **kwargs): - super(EICRecommendationForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['remarks_for_authors'].widget.attrs.update( {'placeholder': 'Your general remarks for the authors', 'rows': 10, 'cols': 100}) diff --git a/submissions/management/__init__.py b/submissions/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/submissions/management/commands/__init__.py b/submissions/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/submissions/management/commands/remind_fellows_to_submit_report.py b/submissions/management/commands/remind_fellows_to_submit_report.py new file mode 100644 index 0000000000000000000000000000000000000000..d7a7a6988cad29edf8318667627eecaaa38d59fd --- /dev/null +++ b/submissions/management/commands/remind_fellows_to_submit_report.py @@ -0,0 +1,13 @@ +from django.core.management.base import BaseCommand +# from django.contrib.auth.models import User + +from ...models import RefereeInvitation +from ...signals import notify_invitation_approaching_deadline, notify_invitation_overdue + + +class Command(BaseCommand): + def handle(self, *args, **options): + for invitation in RefereeInvitation.objects.approaching_deadline(): + notify_invitation_approaching_deadline(RefereeInvitation, invitation, False) + for invitation in RefereeInvitation.objects.overdue(): + notify_invitation_overdue(RefereeInvitation, invitation, False) diff --git a/submissions/managers.py b/submissions/managers.py index e3e15f6c51d24452110bbf3add0da166f5118642..c992faacfdd72f851cbf3377ecd56a348f49af06 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -12,7 +12,9 @@ from .constants import SUBMISSION_STATUS_OUT_OF_POOL, SUBMISSION_STATUS_PUBLICLY STATUS_REJECTED, STATUS_REJECTED_VISIBLE,\ STATUS_ACCEPTED, STATUS_RESUBMITTED, STATUS_RESUBMITTED_REJECTED_VISIBLE,\ EVENT_FOR_EIC, EVENT_GENERAL, EVENT_FOR_AUTHOR,\ - STATUS_UNASSIGNED, STATUS_ASSIGNMENT_FAILED, STATUS_WITHDRAWN + STATUS_UNASSIGNED, STATUS_ASSIGNMENT_FAILED, STATUS_WITHDRAWN,\ + STATUS_PUT_TO_EC_VOTING, STATUS_VOTING_IN_PREPARATION,\ + SUBMISSION_STATUS_VOTING_DEPRECATED, STATUS_REVISION_REQUESTED class SubmissionQuerySet(models.QuerySet): @@ -25,7 +27,7 @@ class SubmissionQuerySet(models.QuerySet): """ # This method used a double query, which is a consequence of the complex distinct() # filter combined with the PostGresQL engine. Without the double query, ordering - # on a specific field after filtering would be impossible. + # on a specific field after filtering seems impossible. ids = (queryset .order_by('arxiv_identifier_wo_vn_nr', '-arxiv_vn_nr') .distinct('arxiv_identifier_wo_vn_nr') @@ -44,26 +46,69 @@ class SubmissionQuerySet(models.QuerySet): except AttributeError: return self.none() - def get_pool(self, user): + def _pool(self, user): """ - Return subset of active and newest 'alive' submissions. + This filter creates 'the complete pool' for an user. This new-style pool does + explicitly not have the author filter anymore, but registered pools for every Submission. + + !!! IMPORTANT SECURITY NOTICE !!! + All permissions regarding Editorial College actions are implicitly taken care + of in this filter method! ALWAYS use this filter method in your Editorial College + related view/action. """ - return (self.user_filter(user) - .exclude(is_current=False) - .exclude(status__in=SUBMISSION_STATUS_OUT_OF_POOL) - .order_by('-submission_date')) + if not hasattr(user, 'contributor'): + return self.none() - def filter_editorial_page(self, user): + if user.has_perm('scipost.can_oversee_refereeing'): + # Editorial Administators do have permission to see all submissions + # without being one of the College Fellows. Therefore, use the 'old' author + # filter to still filter out their conflicts of interests. + return self.user_filter(user) + else: + qs = user.contributor.fellowships.active() + return self.filter(fellows__in=qs) + + def pool(self, user): + """ + Return the pool for a certain user: filtered to "in active referee phase". """ - Return Submissions currently 'alive' (being refereed, not published). + qs = self._pool(user) + qs = qs.exclude(is_current=False).exclude(status__in=SUBMISSION_STATUS_OUT_OF_POOL) + return qs - It is meant to allow opening and editing certain submissions that are officially - out of the submission cycle i.e. due to resubmission, but should still have the - possibility to be opened by the EIC. + def pool_editable(self, user): + """ + Return the editable pool for a certain user. + + This is similar to the regular pool, however it also contains submissions that are + hidden in the regular pool, but should still be able to be opened by for example + the Editor-in-charge. + """ + qs = self._pool(user) + qs = qs.exclude(status__in=SUBMISSION_HTTP404_ON_EDITORIAL_PAGE) + return qs + + def pool_full(self, user): + """ + Return the *FULL* pool for a certain user. + This makes sure the user can see all history of Submissions related to its Fellowship(s). + + Do not use this filter by default however, as this also contains Submissions + that are for example either rejected or accepted already and thus "inactive." + """ + qs = self._pool(user) + return qs + + def filter_for_eic(self, user): + """ + Return the set of Submissions the user is Editor-in-charge for or return the pool if + User is Editorial Administrator. """ - return (self.user_filter(user) - .exclude(status__in=SUBMISSION_HTTP404_ON_EDITORIAL_PAGE) - .order_by('-submission_date')) + qs = self._pool(user) + + if not user.has_perm('scipost.can_oversee_refereeing') and hasattr(user, 'contributor'): + qs = qs.filter(editor_in_charge=user.contributor) + return qs def prescreening(self): """ @@ -77,7 +122,8 @@ class SubmissionQuerySet(models.QuerySet): """ return (self.exclude(is_current=False) .exclude(status__in=SUBMISSION_STATUS_OUT_OF_POOL) - .exclude(status__in=[STATUS_UNASSIGNED, STATUS_ACCEPTED])) + .exclude(status__in=[STATUS_UNASSIGNED, STATUS_ACCEPTED, + STATUS_REVISION_REQUESTED])) def public(self): """ @@ -121,19 +167,18 @@ class SubmissionQuerySet(models.QuerySet): identifiers.append(sub.arxiv_identifier_wo_vn_nr) return self.filter(arxiv_identifier_wo_vn_nr__in=identifiers) - def accepted(self): return self.filter(status=STATUS_ACCEPTED) + def revision_requested(self): + return self.filter(status=STATUS_REVISION_REQUESTED) def published(self): return self.filter(status=STATUS_PUBLISHED) - def assignment_failed(self): return self.filter(status=STATUS_ASSIGNMENT_FAILED) - def rejected(self): return self._newest_version_only(self.filter(status__in=[STATUS_REJECTED, STATUS_REJECTED_VISIBLE])) @@ -141,7 +186,6 @@ class SubmissionQuerySet(models.QuerySet): def withdrawn(self): return self._newest_version_only(self.filter(status=STATUS_WITHDRAWN)) - def open_for_reporting(self): """ Return Submissions that have appriopriate status for reporting. @@ -203,7 +247,7 @@ class EditorialAssignmentQuerySet(models.QuerySet): return self.filter(accepted=None, deprecated=False) -class EICRecommendationManager(models.Manager): +class EICRecommendationQuerySet(models.QuerySet): def get_for_user_in_pool(self, user): """ -- DEPRECATED -- @@ -221,6 +265,8 @@ class EICRecommendationManager(models.Manager): def filter_for_user(self, user, **kwargs): """ + -- DEPRECATED -- + Return list of EICRecommendation's which are owned/assigned author through the related submission. """ @@ -229,6 +275,23 @@ class EICRecommendationManager(models.Manager): except AttributeError: return self.none() + def user_may_vote_on(self, user): + if not hasattr(user, 'contributor'): + return self.none() + + return (self.filter(eligible_to_vote=user.contributor) + .exclude(recommendation__in=[-1, -2]) + .exclude(voted_for=user.contributor) + .exclude(voted_against=user.contributor) + .exclude(voted_abstain=user.contributor) + .exclude(submission__status__in=SUBMISSION_STATUS_VOTING_DEPRECATED)) + + def put_to_voting(self): + return self.filter(submission__status=STATUS_PUT_TO_EC_VOTING) + + def voting_in_preparation(self): + return self.filter(submission__status=STATUS_VOTING_IN_PREPARATION) + class ReportQuerySet(models.QuerySet): def accepted(self): @@ -269,3 +332,17 @@ class RefereeInvitationQuerySet(models.QuerySet): def in_process(self): return self.accepted().filter(fulfilled=False) + + def approaching_deadline(self): + qs = self.in_process() + psuedo_deadline = datetime.datetime.now() + datetime.timedelta(days=2) + deadline = datetime.datetime.now() + qs = qs.filter(submission__reporting_deadline__lte=psuedo_deadline, + submission__reporting_deadline__gte=deadline) + return qs + + def overdue(self): + qs = self.in_process() + deadline = datetime.datetime.now() + qs = qs.filter(submission__reporting_deadline__lte=deadline) + return qs diff --git a/submissions/migrations/0077_auto_20171020_0900.py b/submissions/migrations/0077_auto_20171020_0900.py new file mode 100644 index 0000000000000000000000000000000000000000..26df6de6233dff92c7a78e96c63a55ecf981c55c --- /dev/null +++ b/submissions/migrations/0077_auto_20171020_0900.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-20 07:00 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('colleges', '0001_initial'), + ('proceedings', '0001_initial'), + ('submissions', '0076_auto_20170928_2024'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='fellows', + field=models.ManyToManyField(blank=True, related_name='pool', to='colleges.Fellowship'), + ), + migrations.AddField( + model_name='submission', + name='proceedings', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='proceedings.Proceedings'), + ), + migrations.AlterField( + model_name='submission', + name='submitted_to_journal', + field=models.CharField(choices=[('SciPostPhys', 'SciPost Physics'), ('SciPostPhysLectNotes', 'SciPost Physics Lecture Notes'), ('SciPostPhysProc', 'SciPost Proceedings')], max_length=30, verbose_name='Journal to be submitted to'), + ), + ] diff --git a/submissions/migrations/0078_auto_20171020_1054.py b/submissions/migrations/0078_auto_20171020_1054.py new file mode 100644 index 0000000000000000000000000000000000000000..703f779660ac65d2c5a636484175960f8ac08134 --- /dev/null +++ b/submissions/migrations/0078_auto_20171020_1054.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-20 08:54 +from __future__ import unicode_literals + +from django.db import migrations +from django.db.models import Q + + +def fill_pools(apps, schema_editor): + Fellowship = apps.get_model('colleges', 'Fellowship') + Submission = apps.get_model('submissions', 'Submission') + for fellowship in Fellowship.objects.all(): + # Fellowship.objects.get_or_create(contributor=contributor) + contributor = fellowship.contributor + submissions = Submission.objects.exclude(authors=contributor).exclude( + Q(author_list__icontains=contributor.user.last_name), + ~Q(authors_false_claims=contributor)) + fellowship.pool.add(*submissions) + + +def return_empty(*args, **kwargs): + return + + +class Migration(migrations.Migration): + + dependencies = [ + ('colleges', '0002_auto_20171020_0931'), + ('submissions', '0077_auto_20171020_0900'), + ] + + operations = [ + migrations.RunPython(fill_pools, return_empty), + ] diff --git a/submissions/migrations/0079_auto_20171021_1456.py b/submissions/migrations/0079_auto_20171021_1456.py new file mode 100644 index 0000000000000000000000000000000000000000..a9f4d043d2750ff0b5afcbb95cedf99c14e98f73 --- /dev/null +++ b/submissions/migrations/0079_auto_20171021_1456.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-21 12:56 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0078_auto_20171020_1054'), + ] + + operations = [ + migrations.AlterModelOptions( + name='report', + options={'ordering': ['-date_submitted']}, + ), + migrations.AlterModelOptions( + name='submission', + options={}, + ), + ] diff --git a/submissions/mixins.py b/submissions/mixins.py index 4f84bb7065c9863fe725e231cb6cb02eb08a1a48..467ceab478632e655f21000bbd08b7499f0f099d 100644 --- a/submissions/mixins.py +++ b/submissions/mixins.py @@ -69,8 +69,8 @@ class SubmissionAdminViewMixin(FriendlyPermissionMixin, SubmissionFormViewMixin) """ qs = super().get_queryset() if self.pool: - return qs.get_pool(self.request.user) - return qs.filter_editorial_page(self.request.user) + return qs.pool(self.request.user) + return qs.filter_for_eic(self.request.user) def get_object(self): """ diff --git a/submissions/models.py b/submissions/models.py index e5fb47eb4424289c7bd3dd6f6d1f1d629694db8a..fdacfc9f99876b495e2ec5835d4ffed5a0468c13 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -15,7 +15,7 @@ from .constants import ASSIGNMENT_REFUSAL_REASONS, ASSIGNMENT_NULLBOOL,\ REPORT_STATUSES, STATUS_UNVETTED, SUBMISSION_EIC_RECOMMENDATION_REQUIRED,\ SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC,\ EVENT_GENERAL, EVENT_TYPES, EVENT_FOR_AUTHOR, EVENT_FOR_EIC -from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationManager,\ +from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationQuerySet,\ ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet from .utils import ShortSubmissionCycle, DirectRecommendationSubmissionCycle,\ GeneralSubmissionCycle @@ -24,17 +24,18 @@ from comments.models import Comment from scipost.behaviors import TimeStampedModel from scipost.constants import TITLE_CHOICES from scipost.fields import ChoiceArrayField -from scipost.models import Contributor from scipost.constants import SCIPOST_DISCIPLINES, SCIPOST_SUBJECT_AREAS from journals.constants import SCIPOST_JOURNALS_SUBMIT, SCIPOST_JOURNALS_DOMAINS from journals.models import Publication -############### -# Submissions: -############### class Submission(models.Model): - # Main submission fields + """ + Submission is a SciPost register of an ArXiv article. This object is the central + instance for every action, recommendation, communication, etc. etc. that is related to the + refereeing cycle of a Submission. A possible Publication object is later directly related + to this Submission instance. + """ author_comments = models.TextField(blank=True) author_list = models.CharField(max_length=1000, verbose_name="author list") discipline = models.CharField(max_length=20, choices=SCIPOST_DISCIPLINES, default='physics') @@ -54,10 +55,12 @@ class Submission(models.Model): models.CharField(max_length=10, choices=SCIPOST_SUBJECT_AREAS), blank=True, null=True) - # Status set by Editors + # Refereeing fields status = models.CharField(max_length=30, choices=SUBMISSION_STATUS, default=STATUS_UNASSIGNED) refereeing_cycle = models.CharField(max_length=30, choices=SUBMISSION_CYCLES, default=CYCLE_DEFAULT) + fellows = models.ManyToManyField('colleges.Fellowship', blank=True, + related_name='pool') subject_area = models.CharField(max_length=10, choices=SCIPOST_SUBJECT_AREAS, verbose_name='Primary subject area', default='Phys:QP') submission_type = models.CharField(max_length=10, choices=SUBMISSION_TYPE, @@ -68,6 +71,8 @@ class Submission(models.Model): # Replace this by foreignkey? submitted_to_journal = models.CharField(max_length=30, choices=SCIPOST_JOURNALS_SUBMIT, verbose_name="Journal to be submitted to") + proceedings = models.ForeignKey('proceedings.Proceedings', null=True, blank=True, + related_name='submissions') title = models.CharField(max_length=300) # Authors which have been mapped to contributors: @@ -105,9 +110,7 @@ class Submission(models.Model): objects = SubmissionQuerySet.as_manager() class Meta: - permissions = ( - ('can_take_editorial_actions', 'Can take editorial actions'), - ) + app_label = 'submissions' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -131,8 +134,8 @@ class Submission(models.Model): else: header += ' (deprecated version ' + str(self.arxiv_vn_nr) + ')' try: - header += ' (published as %s (%s))' % (self.publication.doi_string, - self.publication.publication_date.strftime('%Y')) + header += ' (published as %s (%s))' % ( + self.publication.doi_string, self.publication.publication_date.strftime('%Y')) except Publication.DoesNotExist: pass return header @@ -167,21 +170,37 @@ class Submission(models.Model): def get_absolute_url(self): return reverse('submissions:submission', args=[self.arxiv_identifier_w_vn_nr]) + @property + def notification_name(self): + return self.arxiv_identifier_w_vn_nr + + @property def eic_recommendation_required(self): - return self.status not in SUBMISSION_EIC_RECOMMENDATION_REQUIRED + return self.status in SUBMISSION_EIC_RECOMMENDATION_REQUIRED @property def reporting_deadline_has_passed(self): return timezone.now() > self.reporting_deadline + @property + def original_submission_date(self): + return Submission.objects.filter( + arxiv_identifier_wo_vn_nr=self.arxiv_identifier_wo_vn_nr).first().submission_date + @cached_property def other_versions(self): + """ + Return all other versions of the Submission that are publicly accessible. + """ return Submission.objects.public().filter( arxiv_identifier_wo_vn_nr=self.arxiv_identifier_wo_vn_nr ).exclude(pk=self.id).order_by('-arxiv_vn_nr') @cached_property def other_versions_pool(self): + """ + Return all other versions of the Submission. + """ return Submission.objects.filter( arxiv_identifier_wo_vn_nr=self.arxiv_identifier_wo_vn_nr ).exclude(pk=self.id).order_by('-arxiv_vn_nr') @@ -260,9 +279,15 @@ class SubmissionEvent(SubmissionRelatedObjectMixin, TimeStampedModel): ###################### class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model): + """ + EditorialAssignment is a registration for Fellows of their duties of being a + Editor-in-charge for a specific Submission. This model could start as a invitation only, + which should then be accepted or declined by the invited. + """ submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE) to = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE) accepted = models.NullBooleanField(choices=ASSIGNMENT_NULLBOOL, default=None) + # attribute `deprecated' becomes True if another Fellow becomes Editor-in-charge deprecated = models.BooleanField(default=False) completed = models.BooleanField(default=False) @@ -285,6 +310,10 @@ class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model): def get_absolute_url(self): return reverse('submissions:assignment_request', args=(self.id,)) + @property + def notification_name(self): + return self.submission.arxiv_identifier_w_vn_nr + class RefereeInvitation(SubmissionRelatedObjectMixin, models.Model): submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, @@ -316,12 +345,19 @@ class RefereeInvitation(SubmissionRelatedObjectMixin, models.Model): self.submission.title[:30] + ' by ' + self.submission.author_list[:30] + ', invited on ' + self.date_invited.strftime('%Y-%m-%d')) + def get_absolute_url(self): + return reverse('submissions:accept_or_decline_ref_invitations', args=(self.id,)) + @property def referee_str(self): if self.referee: return str(self.referee) return self.last_name + ', ' + self.first_name + @property + def notification_name(self): + return self.submission.arxiv_identifier_w_vn_nr + def reset_content(self): self.nr_reminders = 0 self.date_last_reminded = None @@ -409,9 +445,6 @@ class Report(SubmissionRelatedObjectMixin, models.Model): unique_together = ('submission', 'report_nr') default_related_name = 'reports' ordering = ['-date_submitted'] - permissions = ( - ('can_vet_submitted_reports', 'Can vet submitted Reports'), - ) def __str__(self): return (self.author.user.first_name + ' ' + self.author.user.last_name + ' on ' + @@ -430,6 +463,10 @@ class Report(SubmissionRelatedObjectMixin, models.Model): def get_absolute_url(self): return self.submission.get_absolute_url() + '#report_' + str(self.report_nr) + @property + def notification_name(self): + return self.submission.arxiv_identifier_w_vn_nr + @property def doi_string(self): if self.doi_label: @@ -451,17 +488,16 @@ class Report(SubmissionRelatedObjectMixin, models.Model): Check if current Report is a `FollowupReport`. A Report is a `FollowupReport` if the author of the report already has a vetted report in the series of the specific Submission. """ - return (self.author.reports.accepted() - .filter(submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr, - submission__arxiv_vn_nr__lt=self.submission.arxiv_vn_nr) - .exists()) + return (self.author.reports.accepted().filter( + submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr, + submission__arxiv_vn_nr__lt=self.submission.arxiv_vn_nr).exists()) def latest_report_from_series(self): """ Get latest Report from the same author for the Submission series. """ - return (self.author.reports.accepted() - .filter(submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr) + return (self.author.reports.accepted().filter( + submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr) .order_by('submission__arxiv_identifier_wo_vn_nr').last()) @@ -494,12 +530,12 @@ class EditorialCommunication(SubmissionRelatedObjectMixin, models.Model): return output -############################ -# Editorial Recommendation # -############################ - -# From the Editor-in-charge of a Submission class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): + """ + The EICRecommendation is the recommendation of a Submission written by + the Editor-in-charge made at the end of the refereeing cycle. It can be voted for by + a subset of Fellows and should contain the actual publication decision. + """ submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, related_name='eicrecommendations') date_submitted = models.DateTimeField('date submitted', default=timezone.now) @@ -520,7 +556,7 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): related_name='voted_abstain') voting_deadline = models.DateTimeField('date submitted', default=timezone.now) - objects = EICRecommendationManager() + objects = EICRecommendationQuerySet.as_manager() def __str__(self): return (self.submission.title[:20] + ' by ' + self.submission.author_list[:30] + @@ -530,6 +566,10 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): # TODO: Fix this weird redirect, but it's neccesary for the notifications to have one. return self.submission.get_absolute_url() + @property + def notification_name(self): + return self.submission.arxiv_identifier_w_vn_nr + @property def nr_for(self): return self.voted_for.count() @@ -544,7 +584,10 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): class iThenticateReport(TimeStampedModel): - # is_pending = models.BooleanField(default=True) + """ + iThenticateReport is the SciPost register of an iThenticate report. It saves + basic information coming from iThenticate into the SciPost database for easy access. + """ uploaded_time = models.DateTimeField(null=True, blank=True) processed_time = models.DateTimeField(null=True, blank=True) doc_id = models.IntegerField(primary_key=True) diff --git a/submissions/signals.py b/submissions/signals.py index d14134ba0d4753b025f251d8f2a8ca04cf406460..be833cb833d351eab88e1d0d384e638ef4992762 100644 --- a/submissions/signals.py +++ b/submissions/signals.py @@ -1,5 +1,7 @@ from django.contrib.auth.models import User, Group +from notifications.constants import NOTIFICATION_REFEREE_DEADLINE, NOTIFICATION_REFEREE_OVERDUE +from notifications.models import Notification from notifications.signals import notify @@ -49,3 +51,37 @@ def notify_new_referee_invitation(sender, instance, created, **kwargs): notify.send(sender=sender, recipient=instance.referee.user, actor=instance.submission.editor_in_charge, verb=' would like to invite you to referee a Submission.', target=instance) + + +def notify_invitation_approaching_deadline(sender, instance, created, **kwargs): + """ + Notify Referee its unfinished duty is approaching the deadline. + """ + if instance.referee: + notifications = Notification.objects.filter( + recipient=instance.referee.user, internal_type=NOTIFICATION_REFEREE_DEADLINE).unread() + if not notifications.exists(): + # User doesn't already have a notification to remind him. + administration = Group.objects.get(name='Editorial Administrators') + notify.send(sender=sender, recipient=instance.referee.user, + actor=administration, + verb=(' would like to remind you that your Refereeing Task is ' + 'approaching its deadline, please submit your Report'), + target=instance.submission, type=NOTIFICATION_REFEREE_DEADLINE) + + +def notify_invitation_overdue(sender, instance, created, **kwargs): + """ + Notify Referee its unfinished duty is overdue. + """ + if instance.referee: + notifications = Notification.objects.filter( + recipient=instance.referee.user, internal_type=NOTIFICATION_REFEREE_OVERDUE).unread() + if not notifications.exists(): + # User doesn't already have a notification to remind him. + administration = Group.objects.get(name='Editorial Administrators') + notify.send(sender=sender, recipient=instance.referee.user, + actor=administration, + verb=(' would like to remind you that your Refereeing Task is overdue, ' + 'please submit your Report'), + target=instance.submission, type=NOTIFICATION_REFEREE_OVERDUE) diff --git a/submissions/templates/partials/submissions/pool/submission_assignment_request.html b/submissions/templates/partials/submissions/pool/submission_assignment_request.html new file mode 100644 index 0000000000000000000000000000000000000000..4a96fa72d300958b7de5768b244a8ccd0ba72349 --- /dev/null +++ b/submissions/templates/partials/submissions/pool/submission_assignment_request.html @@ -0,0 +1,37 @@ +{% load bootstrap %} + + +{% include 'submissions/_submission_summary.html' with submission=assignment.submission %} + +<h2 class="highlight">Accept or Decline this Assignment</h2> +<h3 class="mb-2">By accepting, you will be required to start a refereeing round on the next screen.</h3> + +<form action="{% url 'submissions:assignment_request' assignment_id=assignment.id %}" method="post"> + {% csrf_token %} + <div class="form-group row"> + <div class="col-12"> + {{ consider_assignment_form.accept|bootstrap:'0,12' }} + </div> + </div> + <div class="row" id="ref_reason"> + <div class="col-12"> + <p>Please select a reason for declining this assignment</p> + {{ consider_assignment_form.refusal_reason|bootstrap:'0,12' }} + </div> + </div> + <input class="btn btn-primary" type="submit" value="Submit" /> +</form> + + +<script> + $(function() { + $('[name="accept"]').on('change', function() { + var val = $('[name="accept"]:checked').val(); + if(val == 'True') { + $('#ref_reason').hide(); + } else { + $('#ref_reason').show(); + } + }).trigger('change'); + }); +</script> diff --git a/submissions/templates/partials/submissions/pool/submission_details.html b/submissions/templates/partials/submissions/pool/submission_details.html index 032739c452da25847ed4887f2cc669d4f9af6e3c..770936a3dfb2bd08e486a1633e606d8058c36120 100644 --- a/submissions/templates/partials/submissions/pool/submission_details.html +++ b/submissions/templates/partials/submissions/pool/submission_details.html @@ -1,15 +1,22 @@ -{% load guardian_tags %} {% load scipost_extras %} {% load submissions_extras %} {% load user_groups %} -{% get_obj_perms request.user for submission as "sub_perms" %} -{% is_edcol_admin request.user as is_ECAdmin %} +{% is_editor_in_charge request.user submission as is_editor_in_charge %} +{% is_edcol_admin request.user as is_editorial_admin %} -<div class="card submission-detail"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=submission %} - <div class="card-body"> +<hr> +<div class="bg-white submission-detail mt-1"> + <div class="text-center mb-1"> + <a href="javascript:;" class="d-inline-block px-3" data-toggle="hide" data-target="#container_{{ submission.id }}">Hide details <i class="fa fa-angle-up text-blue" aria-hidden="true"></i></a> + </div> + + <div class="card-body px-0"> + {% include 'partials/submissions/pool/submission_info_table.html' with submission=submission %} + </div> + + <div> <h3>Remarks on this submission:</h3> {% if remark_form %} {% include 'submissions/_remark_add_form.html' with submission=submission form=remark_form auto_show=1 %} @@ -23,14 +30,15 @@ {% endfor %} </ul> - {% if "can_take_editorial_actions" in sub_perms or is_ECAdmin %} + {% if is_editor_in_charge or is_editorial_admin %} + <br> {% include 'submissions/_required_actions_block.html' with submission=submission %} <h4> <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Go to this Submission's Editorial Page</a> </h4> {% endif %} - {% if is_ECAdmin %} + {% if is_editorial_admin %} <h3>Editorial Administration</h3> <ul class="pl-4 mb-3"> {# EIC Assignments #} @@ -86,4 +94,8 @@ </div> {% endif %} </div> + + <div class="text-center mb-1"> + <a href="javascript:;" class="d-inline-block px-3" data-toggle="hide" data-target="#container_{{ submission.id }}">Hide details <i class="fa fa-angle-up text-blue" aria-hidden="true"></i></a> + </div> </div> diff --git a/submissions/templates/partials/submissions/pool/submission_info_table.html b/submissions/templates/partials/submissions/pool/submission_info_table.html new file mode 100644 index 0000000000000000000000000000000000000000..62ae68a23c23a9f5d0826dc998502880cbfa4c8d --- /dev/null +++ b/submissions/templates/partials/submissions/pool/submission_info_table.html @@ -0,0 +1,84 @@ +<table class="w-100 mb-1"> + <tr> + <td style="min-width: 40%;">Version</td> + <td>{{submission.arxiv_vn_nr}} ({% if submission.is_current %}current version{% else %}deprecated version {{submission.arxiv_vn_nr}}{% endif %})</td> + </tr> + <tr> + <td>Submitted</td> + <td>{{submission.submission_date}} to {{submission.get_submitted_to_journal_display}}</td> + </tr> + + {% if submission.acceptance_date %} + <tr> + <td>Accepted</td> + <td>{{submission.acceptance_date}}</td> + </tr> + {% endif %} + + <tr> + <td>Latest activity</td> + <td>{{submission.latest_activity}}</td> + </tr> + <tr> + <td>Editor-in-charge</td> + <td> + {% if submission.editor_in_charge %} + {{ submission.editor_in_charge }} + {% elif perms.scipost.can_assign_submissions %} + <a href="{% url 'submissions:assign_submission' submission.arxiv_identifier_w_vn_nr %}">Send a new assignment request</a> + {% else %} + <strong class="text-danger">You can volunteer to become Editor-in-charge by <a href="{% url 'submissions:volunteer_as_EIC' submission.arxiv_identifier_w_vn_nr %}">clicking here</a>.</strong> + {% endif %} + </td> + </tr> + <tr> + <td>Status</td> + <td>{{ submission.get_status_display }}</td> + </tr> + <tr> + <td>Refereeing cycle</td> + <td>{{ submission.get_refereeing_cycle_display }}</td> + </tr> + + {% include 'partials/submissions/refereeing_status_as_tr.html' with submission=submission %} + + <tr> + <td>Comments</td> + <td> + {{submission.comments.vetted.count}} + <small><span class="fa fa-info-circle" data-toggle="tooltip" data-placement='bottom' data-html="true" title="{{submission.comments.regular_comments.vetted.count}} comments<br>{{submission.comments.author_replies.vetted.count}} author replies<hr>{{submission.comments.awaiting_vetting.count}} awaiting vetting"></span></small> + </td> + </tr> + + <tr> + <td>Reporting deadline</td> + <td> + {% if submission.reporting_deadline > now %} + in {{ submission.reporting_deadline|timeuntil }} + {% else %} + {{ submission.reporting_deadline|timesince }} ago + {% endif %} + </td> + </tr> + + {% if perms.scipost.can_do_plagiarism_checks %} + <tr> + <td>Plagiarism score</td> + <td> + {% if submission.plagiarism_report %} + {{ submission.plagiarism_report.score }}% + {% else %} + <a href="{% url 'submissions:plagiarism' submission.arxiv_identifier_w_vn_nr %}">Run plagiarism check</a> + {% endif %} + </td> + </tr> + {% endif %} + + {% if perms.scipost.can_manage_college_composition %} + <tr> + <td>Pool composition</td> + <td><a href="{% url 'colleges:submission' submission.arxiv_identifier_w_vn_nr %}">{{ submission.fellows.count }} Fellowships</a></td> + </tr> + {% endif %} + +</table> diff --git a/submissions/templates/partials/submissions/pool/submission_li.html b/submissions/templates/partials/submissions/pool/submission_li.html index f56f5df73002123e71f31d908920f7cc9d0bfa47..fdd9854706c11655521eb30a85470216a5f4aeef 100644 --- a/submissions/templates/partials/submissions/pool/submission_li.html +++ b/submissions/templates/partials/submissions/pool/submission_li.html @@ -1,37 +1,52 @@ -<div class="row pool-item mb-0"> - <div class="icons{% if is_current %} text-info{% endif %}"> - {% include 'partials/submissions/pool/submission_tooltip.html' with submission=submission %} +<div class="icons"> + {% include 'partials/submissions/pool/submission_tooltip.html' with submission=submission %} - {% if submission.status == 'unassigned' %} - <i class="fa fa-exclamation mt-1 px-1 text-danger" data-toggle="tooltip" data-html="true" title="You can volunteer to become Editor-in-charge"></i> - {% endif %} - </div> - <div class="item col-auto"> - <p class="mb-1"> - <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}">{{ submission.title }}</a><br> - <em>by {{ submission.author_list }}</em> - </p> + {% if submission.status == 'unassigned' %} + <i class="fa fa-exclamation mt-1 px-1 text-danger" data-toggle="tooltip" data-html="true" title="You can volunteer to become Editor-in-charge"></i> + {% endif %} +</div> +<div class="pool-item"> + <p class="mb-1"> + <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}">{{ submission.title }}</a><br> + <em>by {{ submission.author_list }}</em> + </p> - <p class="card-text mb-3"> - <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}" data-toggle="dynamic" data-target="#details">See details</a> + <div class="row mb-0"> + <div class="col-3"> + <small class="text-muted">Editor-in-charge</small> + <br> + {% if submission.status == 'unassigned' %} + <span class="card-text text-danger">You can volunteer to become Editor-in-charge by <a href="{% url 'submissions:volunteer_as_EIC' submission.arxiv_identifier_w_vn_nr %}">clicking here</a>.</span> + {% elif submission.editor_in_charge == request.user.contributor %} + <strong>You are Editor-in-charge</strong> + {% else %} + {{ submission.editor_in_charge }} + {% endif %} + </div> + <div class="col-2"> + <small class="text-muted">Actions</small> + <br> + <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}" data-toggle="dynamic" data-target="#container_{{ submission.id }}">See details</a> {% if submission.editor_in_charge == request.user.contributor %} - · <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Go directly to editorial page</a> + · <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Editorial page</a> {% endif %} - </p> - - {% if submission.cycle.has_required_actions and submission.cycle.get_required_actions %} - <p class="card-text bg-danger text-white p-1 px-2">This Submission contains required actions, <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}" class="text-white" data-toggle="dynamic" data-target="#details">click to see details.</a> {% include 'partials/submissions/pool/required_actions_tooltip.html' with submission=submission classes='text-white' %}</p> - {% endif %} - - {% if submission.status == 'unassigned' %} - <p class="card-text text-danger">You can volunteer to become Editor-in-charge by <a href="{% url 'submissions:volunteer_as_EIC' submission.arxiv_identifier_w_vn_nr %}">clicking here</a>.</p> - {% elif submission.editor_in_charge == request.user.contributor %} - <p class="card-text"><strong>You are Editor-in-charge</strong></p> - {% else %} - <p class="card-text">Editor-in-charge: <em>{{ submission.editor_in_charge }}</em></p> - {% endif %} + </div> + <div class="col-2"> + <small class="text-muted">Original Submission date</small> + <br> + {{ submission.original_submission_date }} + </div> + <div class="col-5"> + <small class="text-muted">Status</small> + <br> + <span class="label label-sm label-secondary">{{ submission.get_status_display }}</span> + </div> + </div> - <p class="label label-{% if submission.status == 'unassigned' %}outline-danger{% else %}secondary{% endif %} label-sm">{{ submission.get_status_display }}</p> + {% if submission.cycle.has_required_actions and submission.cycle.get_required_actions %} + <div class="card-text bg-danger text-white mt-1 py-1 px-2"> + This Submission contains required actions, <a href="{% url 'submissions:pool' submission.arxiv_identifier_w_vn_nr %}" class="text-white" data-toggle="dynamic" data-target="#container_{{ submission.id }}">click to see details.</a> {% include 'partials/submissions/pool/required_actions_tooltip.html' with submission=submission classes='text-white' %} + </div> + {% endif %} - </div> </div> diff --git a/submissions/templates/partials/submissions/pool/submissions_list.html b/submissions/templates/partials/submissions/pool/submissions_list.html new file mode 100644 index 0000000000000000000000000000000000000000..addf01aea47f2fdfdb07b898ada3ba8d0f46b8f7 --- /dev/null +++ b/submissions/templates/partials/submissions/pool/submissions_list.html @@ -0,0 +1,20 @@ +<ul class="list-unstyled pool-list mt-2" data-target="active-list"> + <!-- Submissions list --> + {% for sub in submissions %} + <li class="submission py-2{% if sub == submission %} active{% endif %}" id="submission_{{ submission.id }}"> + {% if sub == submission %} + {% include 'partials/submissions/pool/submission_li.html' with submission=sub is_current=1 %} + {% else %} + {% include 'partials/submissions/pool/submission_li.html' with submission=sub is_current=0 %} + {% endif %} + + <div class="loading-container" id="container_{{ sub.id }}"> + {% if submission and submission == sub %} + {% include 'partials/submissions/pool/submission_details.html' with submission=submission remark_form=remark_form is_ECAdmin=is_ECAdmin user=request.user %} + {% endif %} + </div> + </li> + {% empty %} + <li><em>No Submissions found.</em></li> + {% endfor %} +</ul> diff --git a/submissions/templates/partials/submissions/refereeing_invitation_card_content.html b/submissions/templates/partials/submissions/refereeing_invitation_card_content.html new file mode 100644 index 0000000000000000000000000000000000000000..cb77fb4d0f8ffe69b5377d2685b4be0e94e4ceea --- /dev/null +++ b/submissions/templates/partials/submissions/refereeing_invitation_card_content.html @@ -0,0 +1,8 @@ + +<h3 class="card-title">{% if invitation.submission.reporting_deadline_has_passed %}<span class="label label-sm label-danger mr-2">overdue</span> {% endif %}{{ invitation.submission }}</h3> +<h4 class="card-subtitle text-muted">due: {{ invitation.submission.reporting_deadline }}</h4> + +<div class="d-block"> + <a class="d-inline-block" href="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=invitation.submission.arxiv_identifier_w_vn_nr %}">Submit your Report</a> <span class="text-blue">|</span> + <a class="d-inline-block" href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=invitation.submission.arxiv_identifier_w_vn_nr comtype='RtoE' referee_id=request.user.contributor.id %}">Write to the Editor-in-charge</a>. +</div> diff --git a/submissions/templates/partials/submissions/search_card.html b/submissions/templates/partials/submissions/search_card.html index 537ed070cd91eafa4186ada284e3c42247bf5b91..b6dfe91e6dd92b576be2f3b4ce07c8b1f4388df1 100644 --- a/submissions/templates/partials/submissions/search_card.html +++ b/submissions/templates/partials/submissions/search_card.html @@ -1 +1,3 @@ -{% extends 'submissions/_submission_card_content.html' %} +<div class="card-body px-0"> + {% extends 'partials/submissions/submission_card_content.html' %} +</div> diff --git a/submissions/templates/partials/submissions/submission_card_content.html b/submissions/templates/partials/submissions/submission_card_content.html new file mode 100644 index 0000000000000000000000000000000000000000..aa9128c75d3e9ac2f5ff0e87f181f13e5c4bcceb --- /dev/null +++ b/submissions/templates/partials/submissions/submission_card_content.html @@ -0,0 +1,13 @@ +{% include 'partials/submissions/submission_title.html' with submission=submission %} + +{% block card_footer %} + <p class="text-muted mb-0"> + Version {{ submission.arxiv_vn_nr }} ({% if submission.is_current %}current version{% else %}deprecated version {{ submission.arxiv_vn_nr }}{% endif %}) + <br> + {% if submission.publication %} + Published as <a href="{{ submission.publication.get_absolute_url }}">{{ submission.publication.in_issue.in_volume.in_journal.get_abbreviation_citation }} <strong>{{ submission.publication.in_issue.in_volume.number }}</strong>, {{ submission.publication.get_paper_nr }} ({{ submission.publication.publication_date|date:'Y' }})</a> + {% else %} + Submitted {{ submission.submission_date }} to {{ submission.get_submitted_to_journal_display }} + {% endif %} · latest activity: {{ submission.latest_activity }} + </p> +{% endblock %} diff --git a/submissions/templates/partials/submissions/submission_card_content_homepage.html b/submissions/templates/partials/submissions/submission_card_content_homepage.html new file mode 100644 index 0000000000000000000000000000000000000000..8a0ba52f29bbe99148348e51435ef6e926cfd1a8 --- /dev/null +++ b/submissions/templates/partials/submissions/submission_card_content_homepage.html @@ -0,0 +1,7 @@ +{% extends 'partials/submissions/submission_card_content.html' %} + +{% block card_footer %} + <div class="text-muted mb-0"> + Submitted {{submission.submission_date}} to {{submission.get_submitted_to_journal_display}}</span> + </div> +{% endblock %} diff --git a/submissions/templates/partials/submissions/submission_title.html b/submissions/templates/partials/submissions/submission_title.html new file mode 100644 index 0000000000000000000000000000000000000000..8545ab7f5dbc8a51a5521c6139ad7f24183deb04 --- /dev/null +++ b/submissions/templates/partials/submissions/submission_title.html @@ -0,0 +1,7 @@ +<div class="submission_title"> + <h5 class="pb-0 subject_area">{{ submission.get_subject_area_display }}</h5> + <h3 class="card-title mb-0 submisssion_title"> + <a href="{{ submission.get_absolute_url }}">{{ submission.title }}</a> + </h3> + <p class="mb-3 author_list">by {{ submission.author_list }}</p> +</div> diff --git a/submissions/templates/submissions/_recommendation_author_content.html b/submissions/templates/submissions/_recommendation_author_content.html index abfa95c3d32325ed7ad3eeaa56221bb539421f58..d1f4e69cab3d821efa589ee0f8635c866cb3d4b2 100644 --- a/submissions/templates/submissions/_recommendation_author_content.html +++ b/submissions/templates/submissions/_recommendation_author_content.html @@ -1,18 +1,20 @@ -<div class="card-body"> - <h2 class="pb-0 mb-0">Editorial Recommendation</h2> +<div class="card"> + <div class="card-body"> + <h2 class="pb-0 mb-0">Editorial Recommendation</h2> - {% block recommendation_header %} - <h3 class="card-title text-muted">Date {{recommendation.date_submitted}}</h3> - {% endblock %} + {% block recommendation_header %} + <h3 class="card-title text-muted">Date {{recommendation.date_submitted}}</h3> + {% endblock %} - <h3 class="pb-0">Remarks for authors</h3> - <p class="pl-md-3">{{recommendation.remarks_for_authors|default:'-'}}</p> + <h3 class="pb-0">Remarks for authors</h3> + <p class="pl-md-3">{{recommendation.remarks_for_authors|default:'-'}}</p> - <h3 class="pb-0">Requested changes</h3> - <p class="pl-md-3">{{recommendation.requested_changes|default:'-'}}</p> + <h3 class="pb-0">Requested changes</h3> + <p class="pl-md-3">{{recommendation.requested_changes|default:'-'}}</p> - {% block recommendation_before_recommendation %}{% endblock %} + {% block recommendation_before_recommendation %}{% endblock %} - <h3 class="pb-0">Recommendation</h3> - <p class="pl-md-3 mb-0">{{recommendation.get_recommendation_display}}</p> + <h3 class="pb-0">Recommendation</h3> + <p class="pl-md-3 mb-0">{{recommendation.get_recommendation_display}}</p> + </div> </div> diff --git a/submissions/templates/submissions/_refereeing_invitation_card_content.html b/submissions/templates/submissions/_refereeing_invitation_card_content.html deleted file mode 100644 index 383f50fd3d8ea650d0ed908efcce3e7ed7583f54..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_refereeing_invitation_card_content.html +++ /dev/null @@ -1,10 +0,0 @@ -<div class="card-body"> - <h3 class="card-title">{% if invitation.submission.reporting_deadline_has_passed %}<span class="label label-sm label-danger mr-2">overdue</span> {% endif %}{{ invitation.submission }}</h3> - <h4 class="card-subtitle text-muted">due: {{ invitation.submission.reporting_deadline }}</h4> - - <div class="d-block"> - <a class="d-inline-block" href="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=invitation.submission.arxiv_identifier_w_vn_nr %}">Submit your Report</a> <span class="text-blue">|</span> - <a class="d-inline-block" href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=invitation.submission.arxiv_identifier_w_vn_nr comtype='RtoE' referee_id=request.user.contributor.id %}">Write to the Editor-in-charge</a>. - </div> - -</div> diff --git a/submissions/templates/submissions/_single_public_report_without_comments.html b/submissions/templates/submissions/_single_public_report_without_comments.html index 8ffeb8b8f6f1e06bec568d9447ea72492154c18f..5f0a3cf451b00d72550a7e9da77a25270fbf617c 100644 --- a/submissions/templates/submissions/_single_public_report_without_comments.html +++ b/submissions/templates/submissions/_single_public_report_without_comments.html @@ -10,16 +10,16 @@ <h3>{% if report.anonymous %}(chose public anonymity) {% endif %}<a href="{{report.author.get_absolute_url}}">{{ report.author.user.first_name }} {{ report.author.user.last_name }}</a> on {{ report.date_submitted|date:'Y-n-j' }} </h3> - <ul class="publicationClickables"> - {% if report.doi_string %}<li>doi: {{ report.doi_string }}</li>{% endif %} - {% if report.pdf_report %} - <li><a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a></li> - {% endif %} - {% if perms.scipost.can_manage_reports %} - <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> - {% endif %} - </ul> -</div> + <ul class="publicationClickables"> + {% if report.doi_string %}<li>doi: {{ report.doi_string }}</li>{% endif %} + {% if report.pdf_report %} + <li><a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a></li> + {% endif %} + {% if perms.scipost.can_manage_reports %} + <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> + {% endif %} + </ul> + </div> {% if report.flagged %} <h4 class="text-danger font-weight-bold">CAUTION: check if this referee has been flagged by the authors</h4> @@ -52,15 +52,15 @@ <h3>{% if report.anonymous %}Anonymous Report {{report.report_nr}}{% else %}<a href="{{report.author.get_absolute_url}}">{{ report.author.user.first_name }} {{ report.author.user.last_name }}</a>{% endif %} on {{ report.date_submitted|date:'Y-n-j' }}</h3> </h3> - <ul class="publicationClickables"> - {% if report.doi_string %}<li>doi: {{ report.doi_string }}</li>{% endif %} - {% if report.pdf_report %} - <li><a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a></li> - {% endif %} - {% if perms.scipost.can_manage_reports %} - <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> - {% endif %} - </ul> + <ul class="publicationClickables"> + {% if report.doi_string %}<li>doi: {{ report.doi_string }}</li>{% endif %} + {% if report.pdf_report %} + <li><a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a></li> + {% endif %} + {% if perms.scipost.can_manage_reports %} + <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> + {% endif %} + </ul> </div> {% include 'submissions/_single_report_content.html' with report=report %} diff --git a/submissions/templates/submissions/_submission_assignment_request.html b/submissions/templates/submissions/_submission_assignment_request.html deleted file mode 100644 index 4f274474ef169f87858842bf39fdadcec8618868..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_assignment_request.html +++ /dev/null @@ -1,26 +0,0 @@ -{% load bootstrap %} - -<div class="card-body"> - {% include 'submissions/_submission_summary.html' with submission=assignment.submission %} - <br /> -</div> -<div class="card-footer"> - <h1>Accept or Decline this Assignment</h1> - <h3 class="mb-2">By accepting, you will be required to start a refereeing round on the next screen.</h3> - - <form action="{% url 'submissions:assignment_request' assignment_id=assignment.id %}" method="post"> - {% csrf_token %} - <div class="form-group row"> - <div class="col-12"> - {{ consider_assignment_form.accept }} - </div> - </div> - <div class="row" id="ref_reason"> - <div class="col-12"> - <p>Please select a reason for declining this assignment</p> - {{ consider_assignment_form.refusal_reason|bootstrap:'0,12' }} - </div> - </div> - <input class="btn btn-secondary" type="submit" value="Submit" /> - </form> -</div> diff --git a/submissions/templates/submissions/_submission_card_author_content.html b/submissions/templates/submissions/_submission_card_author_content.html deleted file mode 100644 index 1dabd69564b13275a5cc7742cbf8f826e3baeb2f..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_author_content.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block card_block_footer %} - {{block.super}} - <p class="card-text">by {{submission.author_list}}</p> - <p class="card-text text-muted">Version {{submission.arxiv_vn_nr}} ({% if submission.is_current %}current version{% else %}deprecated version {{submission.arxiv_vn_nr}}{% endif %})</p> - <p class="card-text text-muted">Submitted {{submission.submission_date}} to {{submission.get_submitted_to_journal_display}} - latest activity: {{submission.latest_activity}}</p> - <p class="card-text">Status: {{submission.get_status_display}}</p> - - {% if current_user and current_user.contributor == submission.submitted_by %} - <p class="card-text"> - {% if submission.editor_in_charge %} - <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='AtoE' %}">Write to the Editor-in-charge</a> - {% endif %} - {% if submission.status == 'revision_requested' %} - · <a href="{% url 'submissions:prefill_using_identifier' %}?identifier={{submission.arxiv_identifier_wo_vn_nr}}">Resubmit this manuscript</a> - {% endif %} - </p> - {% endif %} -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_base.html b/submissions/templates/submissions/_submission_card_base.html index fa4d0d8c90afdca722169f35e2d1865095471efc..1d3be2c52c30e32892f05b473ad70a2ce46991b3 100644 --- a/submissions/templates/submissions/_submission_card_base.html +++ b/submissions/templates/submissions/_submission_card_base.html @@ -1,8 +1,8 @@ -<div class="card-body {% block cardblock_class_block %}{% endblock %}"> +<div class="submission_title"> <h5 class="pb-0">{{submission.get_subject_area_display}}</h5> <h3 class="card-title {% block title_class_block %}{% endblock %}"> <a href="{{submission.get_absolute_url}}">{{submission.title}}</a> </h3> - - {% block card_block_footer %}{% endblock %} </div> + +{% block card_block_footer %}{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_content.html b/submissions/templates/submissions/_submission_card_content.html deleted file mode 100644 index 900102bc98312f0c8e146a3c4c309d0a04dabfaa..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_content.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block title_class_block %}mb-0{% endblock %} - -{% block card_block_footer %} - {{block.super}} - <p class="card-text mb-3">by {{submission.author_list}}</p> - <p class="card-text text-muted">Version {{submission.arxiv_vn_nr}} ({% if submission.is_current %}current version{% else %}deprecated version {{submission.arxiv_vn_nr}}{% endif %})</p> - <p class="card-text text-muted"> - {% if submission.publication %} - Published as <a href="{{submission.publication.get_absolute_url}}">{{submission.publication.in_issue.in_volume.in_journal.get_abbreviation_citation}} <strong>{{submission.publication.in_issue.in_volume.number}}</strong>, {{submission.publication.get_paper_nr}} ({{submission.publication.publication_date|date:'Y'}})</a> - {% else %} - Submitted {{submission.submission_date}} to {{submission.get_submitted_to_journal_display}} - {% endif %} · latest activity: {{submission.latest_activity}}</p> -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_content_sparse.html b/submissions/templates/submissions/_submission_card_content_sparse.html deleted file mode 100644 index d90db974e82eb305e28193c5df4923e30c674dc6..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_content_sparse.html +++ /dev/null @@ -1,13 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block cardblock_class_block %}px-0{% endblock %} - - -{% block card_block_footer %} - {{block.super}} - <div class="mt-0 mb-3">by {{submission.author_list}}</div> - <div class="text-muted"> - <span class="d-inline-block">Submitted {{submission.submission_date}}</span> - <span class="d-inline-block">to {{submission.get_submitted_to_journal_display}}</span> - </div> -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_contributor_content.html b/submissions/templates/submissions/_submission_card_contributor_content.html deleted file mode 100644 index 4f5b8fbe93eb705b4d1e3f6b7fc01315f7646fc7..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_contributor_content.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block card_block_footer %} - {{block.super}} - <p class="card-text">by {{submission.author_list}}</p> - <p class="card-text text-muted">Submitted {{submission.submission_date}} to {{submission.get_submitted_to_journal_display}}</p> - <p class="card-text text-muted">Status: {{submission.get_status_display}}</p> -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_eic_content.html b/submissions/templates/submissions/_submission_card_eic_content.html deleted file mode 100644 index 41d94af29220d1f0b69ec2e5db8b7edf75c070c1..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_eic_content.html +++ /dev/null @@ -1,8 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block card_block_footer %} - {{block.super}} - <p class="card-text text-muted">by {{submission.author_list}} (submitted {{submission.submission_date}} to {{submission.get_submitted_to_journal_display}})</p> - <p class="card-text text-muted">Status: {{submission.get_status_display}}</p> - <p class="card-text mt-2">Manage this Submission from its <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a>.</p> -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_fellow_content.html b/submissions/templates/submissions/_submission_card_fellow_content.html deleted file mode 100644 index 49c7e881e218d6a7ee18075fcb771ff665ebb658..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/_submission_card_fellow_content.html +++ /dev/null @@ -1,82 +0,0 @@ -{% extends 'submissions/_submission_card_base.html' %} - -{% block card_block_footer %} - <p class="card-text mb-3">by {{submission.author_list}}</p> - <table class="text-muted w-100 mb-1"> - <tr> - <td style="min-width: 40%;">Version</td> - <td>{{submission.arxiv_vn_nr}} ({% if submission.is_current %}current version{% else %}deprecated version {{submission.arxiv_vn_nr}}{% endif %})</td> - </tr> - <tr> - <td>Submitted</td> - <td>{{submission.submission_date}} to {{submission.get_submitted_to_journal_display}}</td> - </tr> - - {% if submission.acceptance_date %} - <tr> - <td>Accepted</td> - <td>{{submission.acceptance_date}}</td> - </tr> - {% endif %} - - <tr> - <td>Latest activity</td> - <td>{{submission.latest_activity}}</td> - </tr> - <tr> - <td>Editor-in-charge</td> - <td> - {% if submission.editor_in_charge %} - {{ submission.editor_in_charge }} - {% elif perms.scipost.can_assign_submissions %} - <a href="{% url 'submissions:assign_submission' submission.arxiv_identifier_w_vn_nr %}">Send a new assignment request</a> - {% else %} - - - {% endif %} - </td> - </tr> - <tr> - <td>Status</td> - <td>{{ submission.get_status_display }}</td> - </tr> - <tr> - <td>Refereeing cycle</td> - <td>{{ submission.get_refereeing_cycle_display }}</td> - </tr> - - {% include 'partials/submissions/refereeing_status_as_tr.html' with submission=submission %} - - <tr> - <td>Comments</td> - <td> - {{submission.comments.vetted.count}} - <small><span class="fa fa-info-circle" data-toggle="tooltip" data-placement='bottom' data-html="true" title="{{submission.comments.regular_comments.vetted.count}} comments<br>{{submission.comments.author_replies.vetted.count}} author replies<hr>{{submission.comments.awaiting_vetting.count}} awaiting vetting"></span></small> - </td> - </tr> - - <tr> - <td>Reporting deadline</td> - <td> - {% if submission.reporting_deadline > now %} - in {{ submission.reporting_deadline|timeuntil }} - {% else %} - {{ submission.reporting_deadline|timesince }} ago - {% endif %} - </td> - </tr> - - {% if perms.scipost.can_do_plagiarism_checks %} - <tr> - <td>Plagiarism score</td> - <td> - {% if submission.plagiarism_report %} - {{ submission.plagiarism_report.score }}% - {% else %} - <a href="{% url 'submissions:plagiarism' submission.arxiv_identifier_w_vn_nr %}">Run plagiarism check</a> - {% endif %} - </td> - </tr> - {% endif %} - - </table> -{% endblock %} diff --git a/submissions/templates/submissions/_submission_card_in_pool.html b/submissions/templates/submissions/_submission_card_in_pool.html index ad484a07864a5b1a45ee339273c28547a87e8cb3..cd69c1f89a6cc73f5e9862b197b9ccf7c96ef382 100644 --- a/submissions/templates/submissions/_submission_card_in_pool.html +++ b/submissions/templates/submissions/_submission_card_in_pool.html @@ -1,9 +1,17 @@ {% load guardian_tags %} {% load scipost_extras %} {% load submissions_extras %} +{% load user_groups %} +{% is_editor_in_charge request.user submission as is_editor_in_charge %} +{% is_edcol_admin request.user as is_editorial_admin %} -{% include 'submissions/_submission_card_fellow_content.html' with submission=submission %} +{# !! TODO: Remove this template as soon as new pool in active !! #} + +<div class="card-body px-0"> + {% include 'partials/submissions/submission_title.html' with submission=submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=submission %} +</div> <div class="card-body"> {% if submission.remarks.all %} @@ -19,8 +27,7 @@ {% include 'submissions/_remark_add_form.html' with submission=submission form=remark_form %} {% endif %} - {% get_obj_perms request.user for submission as "sub_perms" %} - {% if "can_take_editorial_actions" in sub_perms or is_ECAdmin %} + {% if is_editor_in_charge or is_editorial_admin %} {% include 'submissions/_required_actions_block.html' with submission=submission %} <h4> <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}">Go to this Submission's Editorial Page</a> @@ -45,7 +52,7 @@ {% endif %} {% endif %} - {% if is_ECAdmin %} + {% if is_editorial_admin %} <h4> <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='StoE' %}">Send a communication to the Editor-in-charge</a> </h4> diff --git a/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html b/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html deleted file mode 100644 index 3e47b51a043e1f5786e576362a63958d6c054733..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/accept_or_decline_ref_invitation_ack.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends 'scipost/base.html' %} - -{% block pagetitle %}: accept or decline refereeing invitation (ack){% endblock pagetitle %} - -{% block content %} - -{% if invitation.accepted == True %} - <h2>Thank you for agreeing to referee this Submission.</h2> - <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> -{% endif %} - -{% endblock content %} diff --git a/submissions/templates/submissions/accept_or_decline_ref_invitations.html b/submissions/templates/submissions/accept_or_decline_ref_invitations.html index 932ecaa432168d1e5e9369b07dd5d572c23e56fe..b20a59fba2ad3223205d1952dff2fc7a0e94df35 100644 --- a/submissions/templates/submissions/accept_or_decline_ref_invitations.html +++ b/submissions/templates/submissions/accept_or_decline_ref_invitations.html @@ -1,14 +1,19 @@ -{% extends 'scipost/base.html' %} +{% extends 'scipost/_personal_page_base.html' %} {% block pagetitle %}: accept or decline refereeing invitations{% endblock pagetitle %} {% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <span class="breadcrumb-item">Accept or decline refereeing invitations</span> +{% endblock %} + {% block content %} <script> $(document).ready(function(){ - $('[name="accept"]').on('change', function() { if($('[name="accept"]:checked').val() == 'False') { $('#id_refusal_reason').parents('.form-group').show(); @@ -21,7 +26,7 @@ $(document).ready(function(){ </script> -{% if not invitation_to_consider %} +{% if not invitation %} <div class="row"> <div class="col-12"> <h1>There are no Refereeing Invitations for you to consider.</h1> @@ -31,18 +36,18 @@ $(document).ready(function(){ <div class="row"> <div class="col-12"> <h1 class="highlight">SciPost Submission which you are asked to Referee (see below to accept/decline):</h1> - {% include 'submissions/_submission_summary.html' with submission=invitation_to_consider.submission %} + {% include 'submissions/_submission_summary.html' with submission=invitation.submission %} </div> </div> <div class="row"> <div class="col-12"> <h2 class="highlight">Accept or Decline this Refereeing Invitation</h2> <h3>Please let us know if you can provide us with a Report for this Submission:</h3> - <p class="text-muted">We will expect your report by <b>{{invitation_to_consider.submission.reporting_deadline}}</b></p> - <form action="{% url 'submissions:accept_or_decline_ref_invitation_ack' invitation_id=invitation_to_consider.id %}" method="post"> + <p>We will expect your report by <b>{{invitation.submission.reporting_deadline}}</b></p> + <form action="{% url 'submissions:accept_or_decline_ref_invitations' invitation_id=invitation.id %}" method="post"> {% csrf_token %} - {{ form|bootstrap }} - <input type="submit" class="btn btn-secondary" value="Submit" /> + {{ form|bootstrap:'4,8' }} + <input type="submit" class="btn btn-primary" value="Submit" /> </form> </div> </div> diff --git a/submissions/templates/submissions/admin/eic_recommendation_detail.html b/submissions/templates/submissions/admin/eic_recommendation_detail.html deleted file mode 100644 index f23a39ca8801f4f05d342ea65aab60d0368eaa4e..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/admin/eic_recommendation_detail.html +++ /dev/null @@ -1,93 +0,0 @@ -{% extends 'submissions/admin/base.html' %} - -{% block pagetitle %}: editorial recommendation for submission{% endblock pagetitle %} - -{% load scipost_extras %} -{% load bootstrap %} - -{% block breadcrumb_items %} - {{block.super}} - <span class="breadcrumb-item">Editorial Recommendation</span> -{% endblock %} - -{% block content %} - -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h1 class="card-title">Editorial Recommendation for Submission</h1> - <p class="card-text"> - 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 - </p> - </div> - </div> - </div> -</div> - -<h2>Submission</h2> -{% include 'submissions/_submission_summary.html' with submission=submission %} - -<div class="card card-outline-secondary"> - {% include 'submissions/_recommendation_fellow_content.html' with recommendation=object %} - <div class="card-body"> - {% if object.remarks.all %} - <h3 class="card-title">Remarks by Fellows:</h3> - <ul> - {% for remark in object.remarks.all|sort_by:'date' %} - {% include 'partials/submissions/remark_as_li.html' with remark=remark %} - {% endfor %} - </ul> - {% endif %} - - <h3 class="card-title">Fellows eligible to vote:</h3> - <ul> - <li> - {% for eligible in object.eligible_to_vote.all|sort_by:'user__last_name' %} - {{ eligible.user.last_name }}, - {% endfor %} - </li> - </ul> - - <h3 class="card-title">Voting results up to now:</h3> - <ul> - <li> - Agreed: ({{ object.voted_for.all.count }}) - {% for agreed in object.voted_for.all|sort_by:'user__last_name' %} - {{ agreed.user.last_name }}, - {% endfor %} - </li> - <li> - Disagreed: ({{ object.voted_against.all.count }}) - {% for disagreed in object.voted_against.all|sort_by:'user__last_name' %} - {{ disagreed.user.last_name }}, - {% endfor %} - </li> - <li> - Abstained: ({{ object.voted_abstain.all.count }}) - {% for abstained in object.voted_abstain.all|sort_by:'user__last_name' %} - {{ abstained.user.last_name }}, - {% endfor %} - </li> - </ul> - - {% if object.remarks %} - <h3 class="card-title">Remarks:</h3> - <ul> - {% for rem in object.remarks.all %} - <li>{{ rem }}</li> - {% empty %} - <li><em>No remarks</em></li> - {% endfor %} - </ul> - {% endif %} - - <h3>Actions:</h3> - <ul> - <li>To fix the College decision and follow the Editorial Recommendation as is: <a href="{% url 'submissions:fix_College_decision' rec_id=object.id %}">click here</a></li> - <li>To request a modification of the Recommendation to request for revision: click here</li> - </ul> - </div> -</div> -{% endblock content %} diff --git a/submissions/templates/submissions/admin/recommendation.html b/submissions/templates/submissions/admin/recommendation.html index 43deb3def36289814b0ac16ef1e4d9e243765929..52bafd667d02290e165300a5758860e775937492 100644 --- a/submissions/templates/submissions/admin/recommendation.html +++ b/submissions/templates/submissions/admin/recommendation.html @@ -13,49 +13,51 @@ {% block content %} <h1 class="highlight">Editorial Recommendation</h1> - <div class="card card-outline-secondary"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=object.submission %} - </div> + {% include 'partials/submissions/submission_title.html' with submission=object.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=object.submission %} + + <br> + {% include 'submissions/_recommendation_fellow_content.html' with recommendation=object %} - <div class="card card-outline-secondary"> - {% include 'submissions/_recommendation_fellow_content.html' with recommendation=object %} + <br> + <div class="card"> <div class="card-body"> {% if object.remarks.exists %} <h3 class="card-title">Remarks by Fellows:</h3> <ul> {% for remark in object.remarks.all|sort_by:'date' %} {% include 'partials/submissions/remark_as_li.html' with remark=remark %} + {% empty %} + <li>No Remarks found.</li> {% endfor %} </ul> {% endif %} <h3 class="card-title">Fellows eligible to vote:</h3> <ul> - <li> - {% for eligible in object.eligible_to_vote.all|sort_by:'user__last_name' %} - {{ eligible.user.last_name }}, - {% endfor %} - </li> + {% for eligible in object.eligible_to_vote.all|sort_by:'user__last_name' %} + <li>{{ eligible.user.first_name }} {{ eligible.user.last_name }}</li> + {% endfor %} </ul> <h3 class="card-title">Voting results up to now:</h3> <ul> <li> - Agreed: ({{ object.voted_for.all.count }}) + Agreed ({{ object.voted_for.all.count }}): {% for agreed in object.voted_for.all|sort_by:'user__last_name' %} - {{ agreed.user.last_name }}, + {{ agreed.user.last_name }}{% if not forloop.last %},{% endif %} {% endfor %} </li> <li> - Disagreed: ({{ object.voted_against.all.count }}) + Disagreed ({{ object.voted_against.all.count }}): {% for disagreed in object.voted_against.all|sort_by:'user__last_name' %} - {{ disagreed.user.last_name }}, + {{ disagreed.user.last_name }}{% if not forloop.last %},{% endif %} {% endfor %} </li> <li> - Abstained: ({{ object.voted_abstain.all.count }}) + Abstained ({{ object.voted_abstain.all.count }}): {% for abstained in object.voted_abstain.all|sort_by:'user__last_name' %} - {{ abstained.user.last_name }}, + {{ abstained.user.last_name }}{% if not forloop.last %},{% endif %} {% endfor %} </li> </ul> @@ -71,9 +73,9 @@ </ul> {% endif %} </div> - <div class="card-footer"> + <div class="card-footer bg-light py-3"> <h3 class="card-title">Administrative actions on recommendations undergoing voting:</h3> - <ul> + <ul class="mb-0"> <li>To send an email reminder to each Fellow with at least one voting duty: <a href="{% url 'submissions:remind_Fellows_to_vote' %}">click here</a></li> <li>To fix the College decision and follow the Editorial Recommendation as is: <a href="{% url 'submissions:fix_College_decision' rec_id=object.id %}">click here</a></li> <li>To request a modification of the Recommendation to request for revision: click here</li> diff --git a/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html b/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html new file mode 100644 index 0000000000000000000000000000000000000000..b317cf46f6df431693bd35a63ea3b953fdd6cfa8 --- /dev/null +++ b/submissions/templates/submissions/admin/recommendation_prepare_for_voting.html @@ -0,0 +1,80 @@ +{% extends 'submissions/admin/base.html' %} + +{% block pagetitle %}: Prepare Editorial Recommendation for voting{% endblock pagetitle %} + +{% load scipost_extras %} +{% load bootstrap %} + +{% block breadcrumb_items %} + {{block.super}} + <span class="breadcrumb-item">Prepare Editorial Recommendation for voting</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Prepare Editorial Recommendation for Voting</h1> + +{% include 'partials/submissions/submission_title.html' with submission=recommendation.submission %} +{% include 'partials/submissions/pool/submission_info_table.html' with submission=recommendation.submission %} + +<br> +{% include 'submissions/_recommendation_fellow_content.html' with recommendation=object %} + +{% if recommendation.submission.referees_flagged %} + <br> + <h3>Referees flagged upon submission (treat reports with caution):</h3> + <p>{{ recommendation.submission.referees_flagged|linebreaksbr }}</p> +{% endif %} + +<br> +<h2 class="highlight">Select Fellows eligible to vote</h2> +<div class="row"> + <div class="col-md-5"> + <p>Fellows with expertise matching the Submission's subject area:</p> + <ul> + {% for fellow in fellows_with_expertise %} + <li>{{ fellow.contributor.user.first_name }} {{ fellow.contributor.user.last_name }}</li> + {% endfor %} + </ul> + </div> + <div class="col-md-7"> + <form action="{% url 'submissions:prepare_for_voting' rec_id=recommendation.id %}" method="post"> + {% csrf_token %} + {{ eligibility_form|bootstrap:'4,8' }} + <input class="btn btn-primary" type="submit" value="Submit" /> + </form> + </div> +</div> + +<div class="row"> + <div class="col-12"> + {% if coauthorships %} + <div class="card card-outline-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"> + {% for key, value in coauthorships.items %} + <li class="list-group-item pt-3"> + <div class="card-content"> + <h3>For Fellow {{key}}:</h3> + </div> + </li> + {% for entry in value.entries %} + <li class="list-group-item"> + {% include 'submissions/_arxiv_queryresult.html' with item=entry %} + </li> + {% endfor %} + {% endfor %} + </ul> + </div> + </div> + {% else %} + <h3 class="text-success">The system has not identified any coauthorships (from arXiv database)</h3> + {% endif %} + </div> +</div> + +{% endblock %} diff --git a/submissions/templates/submissions/admin/refereeing_overview.html b/submissions/templates/submissions/admin/refereeing_overview.html new file mode 100644 index 0000000000000000000000000000000000000000..398e14c535879434ed3fae731fc7bc8ba1e88f87 --- /dev/null +++ b/submissions/templates/submissions/admin/refereeing_overview.html @@ -0,0 +1,41 @@ +{% extends 'submissions/admin/base.html' %} + +{% block pagetitle %}: overview of refereeing{% endblock pagetitle %} + +{% load scipost_extras %} +{% load bootstrap %} + +{% block breadcrumb_items %} + {{block.super}} + <span class="breadcrumb-item">Refereeing overview</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Refereeing overview</h1> + +{% for submission in submissions_under_refereeing %} + {% if not forloop.first %}<hr/>{% endif %} + + <div class="row"> + <div class="col-12"> + <h3><a href="{{ submission.get_absolute_url }}">{{ submission.title }}</a></h3> + <p>{{ submission.author_list }}</p> + + <div> + Editor-in-charge: {{ submission.editor_in_charge }}<br> + Refereeing deadline: {{ submission.reporting_deadline }}<br> + <br> + Refereeing status summary:<br> + {% include 'submissions/_submission_refereeing_status.html' with submission=submission %} + </div> + + <p class="mb-2">Detail of refereeing invitations:</p> + {% include 'submissions/_submission_refereeing_invitations.html' with submission=submission invitations=submission.referee_invitations.all %} + <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='StoE' %}" target="_blank">Send a communication to the Editor-in-charge</a> + </div> + </div> + +{% endfor %} + +{% endblock content %} diff --git a/submissions/templates/submissions/assignments.html b/submissions/templates/submissions/assignments.html deleted file mode 100644 index e94a003d88658ee021faa3881e201d6d3b16e55e..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/assignments.html +++ /dev/null @@ -1,80 +0,0 @@ -{% extends 'submissions/_pool_base.html' %} - -{% block pagetitle %}: Assignments{% endblock pagetitle %} - -{% block breadcrumb_items %} - {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> - <span class="breadcrumb-item">Your assignments</span> -{% endblock %} - -{% block content %} - -<script> -$(document).ready(function(){ - - $('#ref_reason').hide(); - - $('#id_accept').on('change', function() { - if ($('#id_accept_1').is(':checked')) { - $('#ref_reason').show(); - } - else { - $('#ref_reason').hide(); - } - }); -}); -</script> - -{% if assignments_to_consider %} - <div class="row"> - <div class="col-12"> - <div class="highlight d-block p-3"> - <h1 class="p-0">Assignment request</h1> - <h3 class="p-0 mt-1 d-block text-muted">Can you act as Editor-in-charge? (see below to accept/decline)</h3> - </div> - </div> - </div> - {% for assignment_to_consider in assignments_to_consider %} - <div class="row"> - <div class="col-12"> - <div class="card"> - {% include 'submissions/_submission_assignment_request.html' with assignment=assignment_to_consider %} - </div> - </div> - </div> - {% endfor %} -<hr> -{% endif %} - - -{% if current_assignments %} - <div class="row"> - <div class="col-12"> - <h1 class="highlight">Your current assignments:</h1> - </div> - </div> - {% for assignment in current_assignments %} - {% if not forloop.first %}<hr class="small">{% endif %} - <div class="row "> - <div class="col-lg-8"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=assignment.submission %} - </div> - <div class="col-lg-4"> - {% include 'submissions/_required_actions_block.html' with submission=submission %} - <h4 class="d-block mt-2"> - <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=assignment.submission.arxiv_identifier_w_vn_nr %}">Go to this Submission's Editorial Page</a> - </h4> - </div> - </div> - {% endfor %} -{% else %} - <div class="row"> - <div class="col-12"> - <p>You currently have no assignments to take care of.</p> - </div> - </div> -{% endif %} - - -{% endblock content %} diff --git a/submissions/templates/submissions/communication.html b/submissions/templates/submissions/communication.html index 98a2ce31673380e5f57dfbca885036e2146b6dd6..c360101c9daa43b362dacbe71b367380eddb6b22 100644 --- a/submissions/templates/submissions/communication.html +++ b/submissions/templates/submissions/communication.html @@ -1,4 +1,4 @@ -{% extends 'submissions/_pool_base.html' %} +{% extends 'submissions/pool/base.html' %} {% block pagetitle %}: communication{% endblock pagetitle %} @@ -7,55 +7,45 @@ {% block breadcrumb_items %} {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</a> <span class="breadcrumb-item">Communication</span> {% endblock %} {% block content %} -{% if errormessage %} - <div class="row"> - <div class="col-12"> - <p>{{ errormessage }}</p> - </div> - </div> -{% else %} - <div class="row"> - <div class="col-12"> - <h1 class="highlight">Send a Communication</h1> - {% if comtype == 'EtoA' %} - <p>to the submitting Author of Submission</p> - {% elif comtype == 'AtoE' or comtype == 'RtoE' or comtype == 'StoE' %} - <h3>to the Editor-in-charge of Submission</h3> - {% elif comtype == 'EtoR' %} - <p>to Referee of Submission</p> - {% elif comtype == 'EtoS' %} - <p>to SciPost Editorial Administrators</p> - {% endif %} - <div class="card"> - {% include 'submissions/_submission_card_content.html' with submission=submission %} - </div> - </div> +<div class="card card-grey"> + <div class="card-body"> + <h1 class="pb-0">Send a Communication</h1> + {% if comtype == 'EtoA' %} + <h3>to the submitting Author of Submission</h3> + {% elif comtype == 'AtoE' or comtype == 'RtoE' or comtype == 'StoE' %} + <h3>to the Editor-in-charge of Submission</h3> + {% elif comtype == 'EtoR' %} + <h3>to Referee of Submission</h3> + {% elif comtype == 'EtoS' %} + <h3>to SciPost Editorial Administrators</h3> + {% endif %} </div> - - <div class="row"> - <div class="col-12"> - {% if referee_id %} - <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|bootstrap:'0,12' }} - <input class="btn btn-secondary" type="submit" value="Send communication"/> - </form> - {% else %} - <form action="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype=comtype %}" method="post"> - {% csrf_token %} - {{ form|bootstrap:'0,12' }} - <input class="btn btn-secondary" type="submit" value="Send communication"/> - </form> - {% endif %} - +</div> + +{% include 'partials/submissions/submission_card_content.html' with submission=submission %} + +<br> +<div class="row"> + <div class="col-12"> + {% if referee_id %} + <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|bootstrap:'0,12' }} + <input class="btn btn-primary" type="submit" value="Send communication"/> + </form> + {% else %} + <form action="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype=comtype %}" method="post"> + {% csrf_token %} + {{ form|bootstrap:'0,12' }} + <input class="btn btn-primary" type="submit" value="Send communication"/> + </form> {% endif %} </div> </div> diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html index 6d29d4075433e05a154953719b270919be79b224..2d00f95cf92b39b07187ae85627be9a9046c7b2f 100644 --- a/submissions/templates/submissions/editorial_page.html +++ b/submissions/templates/submissions/editorial_page.html @@ -1,18 +1,20 @@ -{% extends 'submissions/_pool_base.html' %} +{% extends 'submissions/pool/base.html' %} -{% block pagetitle %}: editorial page for submission{% endblock pagetitle %} +{% block pagetitle %}: Editorial Page for Submission{% endblock pagetitle %} {% load scipost_extras %} {% load bootstrap %} +{% load user_groups %} {% block breadcrumb_items %} {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> <span class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</span> {% endblock %} {% block content %} +{% is_edcol_admin request.user as is_editorial_admin %} + <h2>Editorial Page for Submission</h2> <h1 class="text-primary">{{submission.title}}</h1> <h3>by {{submission.author_list}}</h3> @@ -211,11 +213,16 @@ <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 %} {% endif %} - <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> + {% if submission.eic_recommendation_required %} + <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> + {% endif %} </ul> </div> </div> @@ -223,8 +230,13 @@ <h2 class="mt-3">Communications</h2> <ul> - <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><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> + {% if submission.editor_in_charge == request.user.contributor %} + <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><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> + {% endif %} + {% if is_editorial_admin %} + <li><a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='StoE' %}">Draft and send a communication as Editorial Administrator to the Editor-in-charge</a></li> + {% endif %} </ul> <div class="row"> diff --git a/submissions/templates/submissions/eic_recommendation.html b/submissions/templates/submissions/eic_recommendation.html deleted file mode 100644 index 08a04e9e5ed04323ade1b43941778e8bfc24e8d1..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/eic_recommendation.html +++ /dev/null @@ -1,69 +0,0 @@ -{% extends 'submissions/_pool_base.html' %} - -{% block pagetitle %}: editorial recommendation for submission{% endblock pagetitle %} - -{% load scipost_extras %} -{% load bootstrap %} - -{% block breadcrumb_items %} - {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> - <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</a> - <span class="breadcrumb-item">Formulate Editorial Recommendation</span> -{% endblock %} - -{% block content %} - -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h1 class="card-title">Formulate Editorial Recommendation for Submission</h1> - <p class="card-text"> - (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) - </p> - <p class="card-text"> - (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) - </p> - </div> - </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> - <h2>Submission</h2> - {% include 'submissions/_submission_summary.html' with submission=submission %} - </div> -</div> - - -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h1 class="card-title">Your Editorial Recommendation</h1> - <p class="card-text">You recommendation will be processed by the Editorial Administration.</p> - <ul class="mb-0"> - <li>acceptance or rejection: forwarded to the Editorial College for ratification</li> - <li>request for revision: sent directly to the authors</li> - </ul> - </div> - </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> - <form action="{% url 'submissions:eic_recommendation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> - {% csrf_token %} - {{ form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Submit"/> - </form> - </div> -</div> - - -{% endblock content %} diff --git a/submissions/templates/submissions/new_submission.html b/submissions/templates/submissions/new_submission.html index 8e278f366204b9c560033fe9b80da9243c68f2d7..0a12296251de12a1a80c8b11b4d396942437f47a 100644 --- a/submissions/templates/submissions/new_submission.html +++ b/submissions/templates/submissions/new_submission.html @@ -10,12 +10,15 @@ $(document).ready(function(){ $('select#id_submitted_to_journal').on('change', function (){ var selection = $(this).val(); + $("#id_proceedings, #id_submission_type").parents('.form-group').hide() + switch(selection){ case "SciPostPhys": $("#id_submission_type").parents('.form-group').show() break; - default: - $("#id_submission_type").parents('.form-group').hide() + case "SciPostPhysProc": + $("#id_proceedings").parents('.form-group').show() + break; } }).trigger('change'); }); diff --git a/submissions/templates/submissions/pool.html b/submissions/templates/submissions/pool.html index 632bb4fe8b832e60ace7193cee4052cfb862c128..bff975019a340c0e7eb7964b8ca79aaa86994b4e 100644 --- a/submissions/templates/submissions/pool.html +++ b/submissions/templates/submissions/pool.html @@ -21,7 +21,7 @@ <div class="col-lg-8"> {% if is_ECAdmin %} - {% if recommendations_undergoing_voting %} + {% if recommendations.put_to_voting.exists %} <div class="row"> <div class="col-12"> <h3 class="highlight mt-0">Administrative actions on recommendations undergoing voting:</h3> @@ -38,14 +38,17 @@ </div> <div class="row"> - {% for rec in recommendations_undergoing_voting %} + {% for rec in recommendations.put_to_voting %} {% if not forloop.first %} <hr> {% endif %} <div class="col-12" id="undergoing_rec_{{rec.id}}"> - <div class="card card-outline-secondary"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=rec.submission %} + <div class="card"> + <div class="card-body"> + {% include 'partials/submissions/submission_title.html' with submission=rec.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=rec.submission %} + </div> </div> <div class="card card-outline-secondary"> @@ -116,22 +119,25 @@ <hr> {% endif %} - {% if recommendations_to_prepare_for_voting %} + {% if recommendations.voting_in_preparation.exists %} <div class="row"> <div class="col-12"> <h1 class="highlight mt-0">Recommendations to prepare for voting</h1> </div> </div> - {% for rec in recommendations_to_prepare_for_voting %} + {% for rec in recommendations.voting_in_preparation %} {% if not forloop.first %} <hr> {% endif %} <div class="row"> <div class="col-12" id="prepare_rec_{{rec.id}}"> - <div class="card card-outline-secondary"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=rec.submission %} + <div class="card"> + <div class="card-body"> + {% include 'partials/submissions/submission_title.html' with submission=rec.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=rec.submission %} + </div> </div> <div class="card card-outline-secondary"> @@ -163,7 +169,7 @@ <div class="row"> <div class="col-12"> <div class="card"> - {% include 'submissions/_submission_assignment_request.html' with assignment=assignment_to_consider %} + {% include 'partials/submissions/pool/submission_assignment_request.html' with assignment=assignment_to_consider %} </div> </div> </div> @@ -184,8 +190,11 @@ <div class="row"> <div class="col-12"> - <div class="card card-outline-secondary"> - {% include 'submissions/_submission_card_fellow_content.html' with submission=rec.submission %} + <div class="card"> + <div class="card-body"> + {% include 'partials/submissions/submission_title.html' with submission=rec.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=rec.submission %} + </div> </div> <div class="card card-outline-secondary"> @@ -229,7 +238,7 @@ <div class="row"> <div class="col-12"> <!-- Submissions list --> - {% for sub in submissions_in_pool %} + {% for sub in submissions %} <div class="card card-outline-secondary mt-1" id="pool_submission_{{sub.id}}"> {% include 'submissions/_submission_card_in_pool.html' with submission=sub remark_form=remark_form is_ECAdmin=is_ECAdmin user=request.user %} </div> @@ -258,14 +267,14 @@ </div><!-- end status --> {% if is_ECAdmin %} - {% if recommendations_undergoing_voting %} + {% if recommendations.put_to_voting.exists %} <!-- Preparing --> <a href="#rec_filter_voting" data-toggle="collapse" class="collapsed"> <h3 class="card-title text-gray-dark">Recommendations undergoing voting ({{recommendations_undergoing_voting|length}})</h3> </a> <div id="rec_filter_voting" class="collapse"> <ul class="list-group list-group-flush"> - {% for recommendation in recommendations_undergoing_voting %} + {% for recommendation in recommendations.put_to_voting %} <li class="list-group-item"> <div class="card-body"> <a href="#undergoing_rec_{{recommendation.id}}">{{recommendation.submission.title}}</a> @@ -278,14 +287,14 @@ </div><!-- end preparing --> {% endif %} - {% if recommendations_to_prepare_for_voting %} + {% if recommendations.voting_in_preparation.exists %} <!-- Preparing --> <a href="#rec_filter_prepare" data-toggle="collapse" class="collapsed"> <h3 class="card-title text-gray-dark">Recommendations to prepare ({{recommendations_to_prepare_for_voting|length}})</h3> </a> <div id="rec_filter_prepare" class="collapse"> <ul class="list-group list-group-flush"> - {% for recommendation in recommendations_to_prepare_for_voting %} + {% for recommendation in recommendations.voting_in_preparation %} <li class="list-group-item"> <div class="card-body"> <a href="#prepare_rec_{{recommendation.id}}">{{recommendation.submission.title}}</a> @@ -301,11 +310,11 @@ <!-- Pool --> <a href="#pool_filter_submissions" data-toggle="collapse"> - <h3 class="card-title text-gray-dark">Submissions in pool ({{submissions_in_pool|length}})</h3> + <h3 class="card-title text-gray-dark">Submissions in pool ({{submissions|length}})</h3> </a> <div id="pool_filter_submissions" class="collapse show"> <ul class="list-group list-group-flush"> - {% for submission in submissions_in_pool %} + {% for submission in submissions %} <li class="list-group-item"> <div class="card-body" style="overflow: auto;"> <a href="#pool_submission_{{submission.id}}">{{submission.title}}</a> diff --git a/submissions/templates/submissions/pool/assignment_request.html b/submissions/templates/submissions/pool/assignment_request.html index 2f0b46cde76c735220de426c609285ce8f891ef8..358d9711e69c5a40a4027235ce7eba41e3bea8b0 100644 --- a/submissions/templates/submissions/pool/assignment_request.html +++ b/submissions/templates/submissions/pool/assignment_request.html @@ -13,8 +13,15 @@ {% block pagetitle %}: Assignment Request{% endblock pagetitle %} {% block content %} - <h1 class="highlight">Assignment request</h1> - <h3>Can you act as Editor-in-charge? (see below to accept/decline)</h3> - {% include 'submissions/_submission_assignment_request.html' with assignment=assignment consider_assignment_form=form %} +<div class="card card-grey"> + <div class="card-body"> + <h1>Assignment request</h1> + <h3 class="pt-0">Can you act as Editor-in-charge? (see below to accept/decline)</h3> + </div> +</div> +<br> + +{% include 'partials/submissions/pool/submission_assignment_request.html' with assignment=assignment consider_assignment_form=form %} + {% endblock %} diff --git a/submissions/templates/submissions/pool/assignments.html b/submissions/templates/submissions/pool/assignments.html new file mode 100644 index 0000000000000000000000000000000000000000..73dfcb932ee00dbb41e9e8da8c19e13a37ee2f5f --- /dev/null +++ b/submissions/templates/submissions/pool/assignments.html @@ -0,0 +1,40 @@ +{% extends 'submissions/pool/base.html' %} + +{% block pagetitle %}: Your Assignments{% endblock pagetitle %} + +{% block breadcrumb_items %} + {{block.super}} + <span class="breadcrumb-item">Your Assignments</span> +{% endblock %} + +{% block content %} + +{% if assignments_to_consider %} + <h1>Your open Assignment Requests <i class="fa fa-exclamation-circle text-warning"></i></h1> + <h3 class="pt-0 mb-2">Can you act as Editor-in-charge? (click to see details)</h3> + <ul> + {% for assignment in assignments_to_consider %} + <li>On submission: {{ assignment.submission }}<br> + <a href="{% url 'submissions:assignment_request' assignment.id %}">Accept or decline here</a> + </li> + {% endfor %} + </ul> +{% endif %} + + +<h1 class="highlight">Your current assignments:</h1> +{% for assignment in current_assignments %} + {% if not forloop.first %}<hr class="small">{% endif %} + + {% include 'partials/submissions/submission_title.html' with submission=assignment.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=assignment.submission %} + + {% include 'submissions/_required_actions_block.html' with submission=submission %} + <h4 class="d-block mt-2"> + <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=assignment.submission.arxiv_identifier_w_vn_nr %}">Go to this Submission's Editorial Page</a> + </h4> +{% empty %} + <p class="py-2">You currently have no assignments to take care of.</p> +{% endfor %} + +{% endblock content %} diff --git a/submissions/templates/submissions/pool/pool.html b/submissions/templates/submissions/pool/pool.html index 97758bf7d200b5414411822a62b3c25fa99375bd..1607a04b15df42d6a004b7d1b9cc40f7413ee628 100644 --- a/submissions/templates/submissions/pool/pool.html +++ b/submissions/templates/submissions/pool/pool.html @@ -23,18 +23,18 @@ <a href="{% url 'submissions:pool' %}?test=1">See old pool layout</a> <div class="row"> - <div class="col-md-7"> + <div class="col-12"> <h1>SciPost Submissions Pool</h1> {% if is_ECAdmin %} - {% if recommendations_to_prepare_for_voting or recommendations_undergoing_voting %} + {% if recommendations.voting_in_preparation.exists or recommendations.put_to_voting.exists %} <div class="quote-border"> <h2 class="text-primary">Administrative Tasks</h2> - {% if recommendations_to_prepare_for_voting %} + {% if recommendations.voting_in_preparation.exists %} <h3>Recommendations to prepare for voting <i class="fa fa-exclamation-circle text-warning"></i></h3> <ul> - {% for recommendation in recommendations_to_prepare_for_voting %} + {% for recommendation in recommendations.voting_in_preparation %} <li>On Editorial Recommendation: {{ recommendation }}<br> <a href="{% url 'submissions:prepare_for_voting' rec_id=recommendation.id %}">Prepare for voting</a> </li> @@ -42,13 +42,13 @@ </ul> {% endif %} - {% if recommendations_undergoing_voting %} + {% if recommendations.put_to_voting.exists %} <h3>Recommendations undergoing voting <i class="fa fa-exclamation-circle text-warning"></i></h3> <ul class="fa-ul"> - {% for recommendation in recommendations_undergoing_voting %} + {% for recommendation in recommendations.put_to_voting %} <li>{% include 'partials/submissions/admin/recommendation_tooltip.html' with classes='fa-li' recommendation=recommendation %} On Editorial Recommendation: {{ recommendation }}<br> - <a href="{% url 'submissions:admin_recommendation' recommendation.submission.arxiv_identifier_w_vn_nr %}">See Editorial Recommendation</a> + <a href="{% url 'submissions:eic_recommendation_detail' recommendation.submission.arxiv_identifier_w_vn_nr recommendation.id %}">See Editorial Recommendation</a> </li> {% endfor %} </ul> @@ -89,37 +89,35 @@ </form> {% endif %} - <ul class="list-unstyled" data-target="active-list"> - <!-- Submissions list --> - {% for sub in submissions_in_pool %} - <li class="p-2{% if sub == submission %} active{% endif %}"> - {% if sub == submission %} - {% include 'partials/submissions/pool/submission_li.html' with submission=sub is_current=1 %} - {% else %} - {% include 'partials/submissions/pool/submission_li.html' with submission=sub is_current=0 %} - {% endif %} - </li> - {% empty %} - <li> - <h3 class="text-center"><i class="fa fa-question fa-2x"></i><br>No Submissions found.</h3> - </li> - {% endfor %} - </ul> - </div><!-- End page content --> - - <div class="col-md-5" id="details"> - {% if submission %} - {% include 'partials/submissions/pool/submission_details.html' with submission=submission remark_form=remark_form is_ECAdmin=is_ECAdmin user=request.user %} + {% if search_form.status.value %} + <h3>All Submissions with status: <span class="text-primary">{{ search_form.status_verbose }}</span></h3> + {% include 'partials/submissions/pool/submissions_list.html' with submissions=submissions %} {% else %} - <h3><em>Click on a submission to see its summary and actions</em></h3> + <h3>Submissions currently in pre-screening</h3> + {% include 'partials/submissions/pool/submissions_list.html' with submissions=submissions.prescreening %} - {% if is_ECAdmin %} - <h2>All events in the last 24 hours</h2> - <div id="eventslist"> - {% include 'submissions/submission_event_list_general.html' with events=latest_events %} - </div> - {% endif %} + <h3>Submissions currently in active refereeing phase</h3> + {% include 'partials/submissions/pool/submissions_list.html' with submissions=submissions.actively_refereeing %} + + <h3>Submissions awaiting resubmission</h3> + {% include 'partials/submissions/pool/submissions_list.html' with submissions=submissions.revision_requested %} + + <h3>Submissions accepted</h3> + {% include 'partials/submissions/pool/submissions_list.html' with submissions=submissions.accepted %} {% endif %} - </div> + + </div><!-- End page content --> </div> {% endblock %} + +{% comment %} + <h3><em>Click on a submission to see its summary and actions</em></h3> + + {% if is_ECAdmin %} + <h2>All events in the last 24 hours</h2> + <div id="eventslist"> + {% include 'submissions/submission_event_list_general.html' with events=latest_events %} + </div> + {% endif %} + + {% endcomment %} diff --git a/submissions/templates/submissions/pool/recommendation.html b/submissions/templates/submissions/pool/recommendation.html index d2c050bbb0c1b3090e5f8c6d83a35bb2c81c6b24..bf84970079036e734701537e61e42182789945c5 100644 --- a/submissions/templates/submissions/pool/recommendation.html +++ b/submissions/templates/submissions/pool/recommendation.html @@ -12,18 +12,17 @@ {% block content %} <h1>Editorial Recommendation to vote on</h1> - {% include 'submissions/_submission_card_fellow_content.html' with submission=recommendation.submission %} - - {# <div class="card card-outline-secondary">#} - {% include 'submissions/_recommendation_fellow_content.html' with recommendation=recommendation %} - <div class="card-footer"> - <h3>Your position on this recommendation</h3> - <form action="{% url 'submissions:vote_on_rec' rec_id=recommendation.id %}" method="post"> - {% csrf_token %} - {{ form|bootstrap:'0,12' }} - <input type="submit" name="submit" value="Cast your vote" class="btn btn-primary submitButton" id="submit-id-submit"> - </form> - </div> - {# </div>#} + + {% include 'partials/submissions/submission_title.html' with submission=recommendation.submission %} + {% include 'partials/submissions/pool/submission_info_table.html' with submission=recommendation.submission %} + <br> + + {% include 'submissions/_recommendation_fellow_content.html' with recommendation=recommendation %} + <h3 class="mt-4">Your position on this recommendation</h3> + <form action="{% url 'submissions:vote_on_rec' rec_id=recommendation.id %}" method="post"> + {% csrf_token %} + {{ form|bootstrap:'0,12' }} + <input type="submit" name="submit" value="Cast your vote" class="btn btn-primary submitButton" id="submit-id-submit"> + </form> {% endblock %} diff --git a/submissions/templates/submissions/pool/recommendation_formulate.html b/submissions/templates/submissions/pool/recommendation_formulate.html new file mode 100644 index 0000000000000000000000000000000000000000..2ae4a3ce76cf271233f8012359db8eb607af13c7 --- /dev/null +++ b/submissions/templates/submissions/pool/recommendation_formulate.html @@ -0,0 +1,64 @@ +{% extends 'submissions/pool/base.html' %} + +{% block pagetitle %}: Editorial Recommendation for Submission{% endblock pagetitle %} + +{% load scipost_extras %} +{% load bootstrap %} + +{% block breadcrumb_items %} + {{block.super}} + <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</a> + <span class="breadcrumb-item">Formulate Editorial Recommendation</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Formulate Editorial Recommendation for Submission</h1> + +<br> +{% include 'submissions/_submission_summary.html' with submission=submission %} + +<br> +<div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Your Editorial Recommendation</h2> + <p class="card-text">You recommendation will be processed by the Editorial Administration.</p> + <ul class="mb-0"> + <li>acceptance or rejection: forwarded to the Editorial College for ratification</li> + <li>request for revision: sent directly to the authors</li> + </ul> + </div> +</div> + +{% if submission.editor_in_charge != request.user.contributor %} + <div class="row"> + <div class="col-12"> + <div class="card border-danger"> + <div class="card-body d-flex flex-row"> + <div class="p-2"> + <i class="fa fa-2x fa-exclamation-triangle text-warning" aria-hidden="true"></i> + </div> + <div class="px-2"> + You are not assigned as Editor in charge. However, you can formulate an Editorial Recommendation because you are Editorial Administrator. <strong>This Editorial Recommendation will still be signed by the Editor-in-charge.</strong> + </div> + + </div> + </div> + </div> + </div> +{% endif %} + +<br> + +<div class="row"> + <div class="col-12"> + <form action="{% url 'submissions:eic_recommendation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary" type="submit" value="Submit Recommendation"/> + </form> + </div> +</div> + + +{% endblock content %} diff --git a/submissions/templates/submissions/prepare_for_voting.html b/submissions/templates/submissions/prepare_for_voting.html deleted file mode 100644 index 0b26ca06cda441e3dab3c9a70ed28bf06b4c9940..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/prepare_for_voting.html +++ /dev/null @@ -1,105 +0,0 @@ -{% extends 'submissions/_pool_base.html' %} - -{% block pagetitle %}: prepare recommendation for voting{% endblock pagetitle %} - -{% load scipost_extras %} -{% load bootstrap %} - -{% block breadcrumb_items %} - {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> - <a href="{% url 'submissions:editorial_page' recommendation.submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{recommendation.submission.arxiv_identifier_w_vn_nr}})</a> - <span class="breadcrumb-item">Prepare recommendation for voting</span> -{% endblock %} - -{% block content %} - -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h1 class="card-title">Prepare Editorial Recommendation for Voting</h1> - <p class="card-text">(go to the <a href="{% url 'submissions:submission' arxiv_identifier_w_vn_nr=recommendation.submission.arxiv_identifier_w_vn_nr %}">Submissions Page</a> to view Reports and Comments)</p> - <p class="card-text">(go back to the <a href="{% url 'submissions:editorial_page' arxiv_identifier_w_vn_nr=recommendation.submission.arxiv_identifier_w_vn_nr %}">Editorial Page</a> to take editorial actions)</p> - </div> - </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> - <h2>Submission:</h2> - {% include 'submissions/_submission_summary.html' with submission=recommendation.submission %} - - {% if recommendation.submission.referees_flagged %} - <h3>Referees flagged upon submission (treat reports with caution):</h3> - <p>{{ recommendation.submission.referees_flagged }}</p> - {% endif %} - </div> -</div> - - - -<div class="row"> - <div class="col-12"> - <div class="card card-outline-secondary"> - {% include 'submissions/_recommendation_fellow_content.html' with recommendation=recommendation %} - </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> - <h1 class="highlight">Select Fellows eligible to vote</h1> - </div> -</div> -<div class="row"> - <div class="col-md-6"> - <p>Fellows with expertise matching the Submission's subject area:</p> - <ul> - {% for Fellow in Fellows_with_expertise %} - <li>{{ Fellow.user.last_name }}</li> - {% endfor %} - </ul> - </div> - <div class="col-md-6"> - <form action="{% url 'submissions:prepare_for_voting' rec_id=recommendation.id %}" method="post"> - {% csrf_token %} - {{ eligibility_form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Submit" /> - </form> - </div> -</div> - -<div class="row"> - <div class="col-12"> - {% if coauthorships %} - <div class="card card-outline-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"> - {% for key, value in coauthorships.items %} - <li class="list-group-item pt-3"> - <div class="card-content"> - <h3>For Fellow {{key}}:</h3> - </div> - </li> - {% for entry in value.entries %} - <li class="list-group-item"> - {% include 'submissions/_arxiv_queryresult.html' with item=entry %} - </li> - {% endfor %} - {% endfor %} - </ul> - </div> - </div> - {% else %} - <h3 class="text-success">The system has not identified any coauthorships (from arXiv database)</h3> - {% endif %} - </div> -</div> - -{% endblock %} diff --git a/submissions/templates/submissions/refereeing_overview.html b/submissions/templates/submissions/refereeing_overview.html deleted file mode 100644 index cfa01d4dcd69fc930cb87cc111fb78465adfb70e..0000000000000000000000000000000000000000 --- a/submissions/templates/submissions/refereeing_overview.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends 'submissions/_pool_base.html' %} - -{% block pagetitle %}: overview of refereeing{% endblock pagetitle %} - -{% load scipost_extras %} -{% load bootstrap %} - -{% block breadcrumb_items %} - {{block.super}} - <span class="breadcrumb-item">Refereeing overview</span> -{% endblock %} - -{% block content %} - -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h1>Refereeing overview</h1> - </div> - </div> - </div> -</div> - -{% for submission in submissions_under_refereeing %} - -<hr/> -<div class="row"> - <div class="col-12"> - <div class="card mx-1"> - <div class="card-body"> - <h3><a href="{{ submission.get_absolute_url }}">{{ submission.title }}</a></h3> - <p>{{ submission.author_list }}</p> - <h4>Editor-in-charge: {{ submission.editor_in_charge }}</h4> - <h4>Refereeing deadline: {{ submission.reporting_deadline }}</h4> - <h4>Refereeing status summary:</h4> - {% include 'submissions/_submission_refereeing_status.html' with submission=submission %} - <h3 class="mb-2">Detail of refereeing invitations:</h3> - {% include 'submissions/_submission_refereeing_invitations.html' with submission=submission invitations=submission.referee_invitations.all %} - <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='StoE' %}" target="_blank">Send a communication to the Editor-in-charge</a> - </div> - </div> - </div> -</div> - -{% endfor %} - - - -{% endblock content %} diff --git a/submissions/templates/submissions/select_referee.html b/submissions/templates/submissions/select_referee.html index fa7cb6c8877c264bb6dd6b4ce715db1049fb21e6..ecaa27de42430dcc9483b18e0c3b2272a5597677 100644 --- a/submissions/templates/submissions/select_referee.html +++ b/submissions/templates/submissions/select_referee.html @@ -1,4 +1,4 @@ -{% extends 'submissions/_pool_base.html' %} +{% extends 'submissions/pool/base.html' %} {% block pagetitle %}: select referee for submission{% endblock pagetitle %} @@ -7,7 +7,6 @@ {% block breadcrumb_items %} {{block.super}} - <a href="{% url 'submissions:pool' %}" class="breadcrumb-item">Pool</a> <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</a> <span class="breadcrumb-item">Select Referee</span> {% endblock %} @@ -40,12 +39,12 @@ <div class="row"> <div class="col-12"> - <h1 class="highlight" id="form">Select an additional Referee</h1> + <h2 class="highlight" id="form">Select an additional Referee</h2> <form action="{% url 'submissions:select_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}#form" method="post"> {% csrf_token %} {{ ref_search_form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Find referee"> + <input class="btn btn-primary" type="submit" value="Find referee"> </form> </div> </div> diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html index 552fefc9a7b21581f76b724e5b719c905d6be6be..0010c1e89e760112bcce533f491945214cd63edc 100644 --- a/submissions/templates/submissions/submission_detail.html +++ b/submissions/templates/submissions/submission_detail.html @@ -4,20 +4,7 @@ {% load submissions_extras %} {% load bootstrap %} -{% block pagetitle %}: submission detail{% endblock pagetitle %} - -{% block headsup %} - - <script> - $(document).ready(function(){ - $("#invitedreportsbutton").click(function(){ - $("#invitedreportslist").toggle(); - }); - - }); - </script> - -{% endblock headsup %} +{% block pagetitle %} Submission: {{ submission.title|truncatechars:40 }}{% endblock pagetitle %} {% block breadcrumb %} <nav class="breadcrumb py-md-2 px-0"> @@ -30,7 +17,6 @@ {% block content %} - <div class="row"> <div class="col-12"> <h2>SciPost Submission Page</h2> @@ -98,19 +84,12 @@ {% if is_author or user|is_in_group:'Editorial College' or user|is_in_group:'Editorial Administrators' %} {% for recommendation in recommendations %} {% if user|is_in_group:'Editorial College' or user|is_in_group:'Editorial Administrators' or recommendation|is_viewable_by_authors %} - <div class="row"> - <div class="col-12"> - <div class="card card-outline-secondary"> - {% include 'submissions/_recommendation_author_content.html' with recommendation=recommendation %} - </div> - </div> - </div> + {% include 'submissions/_recommendation_author_content.html' with recommendation=recommendation %} {% endif %} {% endfor %} <div class="mb-4"> <h2>Events</h2> - <a href="javascript:;" data-toggle="toggle" data-target="#eventslist">Show/hide events</a> <div id="eventslist"> {% include 'submissions/submission_event_list.html' with events=submission.events.for_author %} </div> diff --git a/submissions/templates/submissions/submissions.html b/submissions/templates/submissions/submissions.html index e257bc0782c9141b0e4e71fa6dde3aab5208193e..05e114e3f2e255678c6c9b80c6ce870f309e436f 100644 --- a/submissions/templates/submissions/submissions.html +++ b/submissions/templates/submissions/submissions.html @@ -50,47 +50,30 @@ {% else %} <h2>Search results:</h3> {% endif %} - {% if object_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for submission in object_list %} - <li class="list-group-item"> - {% include 'submissions/_submission_card_content.html' with submission=submission %} - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} - </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} <div class="col-12"> - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} + <ul class="list-group list-group-flush"> + {% for submission in object_list %} + <li class="list-group-item"> + <div class="card-body px-0"> + {% include 'partials/submissions/submission_card_content.html' with submission=submission %} + </div> + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/submissions/templates/submissions/vet_submitted_report.html b/submissions/templates/submissions/vet_submitted_report.html index 64d36c03c9b7da45bd3285c4f4383d5bf3334f7f..3573610ada85ab771d66ff461358816098391cc2 100644 --- a/submissions/templates/submissions/vet_submitted_report.html +++ b/submissions/templates/submissions/vet_submitted_report.html @@ -57,7 +57,7 @@ $(document).ready(function(){ {{ form.refusal_reason|bootstrap }} {{ form.email_response_field|bootstrap }} </div> - <input class="btn btn-secondary" type="submit" value="Submit" /> + <input class="btn btn-primary" type="submit" value="Submit" /> </form> {% endif %} diff --git a/submissions/templatetags/submissions_extras.py b/submissions/templatetags/submissions_extras.py index 0ec7944d18a2fb3e51a2f06d6f47b791f86c6034..9cb66171d072b47b057a2a2b6e79817614db882c 100644 --- a/submissions/templatetags/submissions_extras.py +++ b/submissions/templatetags/submissions_extras.py @@ -1,8 +1,5 @@ -import datetime - from django import template -from submissions.constants import SUBMISSION_STATUS_OUT_OF_POOL from submissions.models import Submission register = template.Library() diff --git a/submissions/urls.py b/submissions/urls.py index 2b9232e49bee589d62af54a5cb7668bc139f6553..1a10cce67d167e0ad3fa722d52c4c57d0188d9ad 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -39,8 +39,6 @@ urlpatterns = [ views.report_pdf_compile, name='report_pdf_compile'), url(r'^admin/reports/(?P<report_id>[0-9]+)/compile$', views.report_pdf_compile, name='report_pdf_compile'), - url(r'^admin/{regex}/recommendation$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), - views.AdminRecommendationView.as_view(), name='admin_recommendation'), url(r'^submit_manuscript$', views.RequestSubmission.as_view(), name='submit_manuscript'), url(r'^submit_manuscript/prefill$', views.prefill_using_arxiv_identifier, @@ -76,8 +74,8 @@ urlpatterns = [ 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'^accept_or_decline_ref_invitations/(?P<invitation_id>[0-9]+)$', + views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), url(r'^decline_ref_invitation/(?P<invitation_key>.+)$', views.decline_ref_invitation, name='decline_ref_invitation'), url(r'^ref_invitation_reminder/{regex}/(?P<invitation_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), diff --git a/submissions/utils.py b/submissions/utils.py index b741e421aef5c2d531c7cd9cf5536764694deba4..90fad6bad125cb646f92ac9ceea5b9094835cbef 100644 --- a/submissions/utils.py +++ b/submissions/utils.py @@ -1137,19 +1137,19 @@ class SubmissionUtils(BaseMailUtil): recipient_greeting = ('Dear ' + cls.communication.submission.submitted_by.get_title_display() + ' ' + cls.communication.submission.submitted_by.user.last_name) - bcc_emails.append(cls.communication.submission.editor_in_charge) + bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) bcc_emails.append('submissions@scipost.org') elif cls.communication.comtype in ['EtoR']: recipient_email.append(cls.communication.referee.user.email) recipient_greeting = ('Dear ' + cls.communication.referee.get_title_display() + ' ' + cls.communication.referee.user.last_name) - bcc_emails.append(cls.communication.submission.editor_in_charge) + bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) bcc_emails.append('submissions@scipost.org') elif cls.communication.comtype in ['EtoS']: recipient_email.append('submissions@scipost.org') recipient_greeting = 'Dear Editorial Administrators' - bcc_emails.append(cls.communication.submission.editor_in_charge) + bcc_emails.append(cls.communication.submission.editor_in_charge.user.email) further_action_page = 'https://scipost.org/submissions/pool' email_text = (recipient_greeting + diff --git a/submissions/views.py b/submissions/views.py index b0fbd035edfcb72d960c8a2889e03ea2e9d41e1f..14a1ef4c7614f98c6d1b77993f6de87283a6bf42 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -7,7 +7,7 @@ from django.contrib.auth.models import Group from django.core.urlresolvers import reverse, reverse_lazy from django.db import transaction, IntegrityError from django.http import Http404, HttpResponse, HttpResponseRedirect -from django.shortcuts import get_object_or_404, render, redirect +from django.shortcuts import get_object_or_404, get_list_or_404, render, redirect from django.template import Template, Context from django.utils import timezone from django.utils.decorators import method_decorator @@ -16,10 +16,9 @@ from django.views.generic.detail import DetailView, SingleObjectMixin from django.views.generic.edit import CreateView, UpdateView from django.views.generic.list import ListView -from guardian.decorators import permission_required_or_403 -from guardian.shortcuts import assign_perm, get_objects_for_user +from guardian.shortcuts import assign_perm -from .constants import SUBMISSION_STATUS_VOTING_DEPRECATED, STATUS_VETTED, STATUS_EIC_ASSIGNED,\ +from .constants import STATUS_VETTED, STATUS_EIC_ASSIGNED,\ SUBMISSION_STATUS_PUBLICLY_INVISIBLE, SUBMISSION_STATUS, ED_COMM_CHOICES,\ STATUS_DRAFT, CYCLE_DIRECT_REC from .models import Submission, EICRecommendation, EditorialAssignment,\ @@ -36,6 +35,7 @@ from .utils import SubmissionUtils from mails.views import MailEditingSubView from scipost.forms import ModifyPersonalMessageForm, RemarkForm +from scipost.mixins import PaginationMixin from scipost.models import Contributor, Remark, RegistrationInvitation from scipost.utils import Utils from scipost.permissions import is_tester @@ -123,7 +123,7 @@ def prefill_using_arxiv_identifier(request): return render(request, 'submissions/prefill_using_identifier.html', context) -class SubmissionListView(ListView): +class SubmissionListView(PaginationMixin, ListView): model = Submission template_name = 'submissions/submissions.html' form = SubmissionSearchForm @@ -339,61 +339,54 @@ def pool(request, arxiv_identifier_w_vn_nr=None): to publication acceptance or rejection. All members of the Editorial College have access. """ - submissions_in_pool = (Submission.objects.get_pool(request.user) - .prefetch_related('referee_invitations', 'remarks', 'comments')) - recommendations_undergoing_voting = (EICRecommendation.objects - .get_for_user_in_pool(request.user) - .filter(submission__status='put_to_EC_voting')) - recommendations_to_prepare_for_voting = (EICRecommendation.objects - .get_for_user_in_pool(request.user) - .filter( - submission__status='voting_in_preparation')) - contributor = Contributor.objects.get(user=request.user) - assignments_to_consider = EditorialAssignment.objects.open().filter(to=contributor) + # Objects + + # The following is in test phase. Update if test is done + # -- + # Search + search_form = SubmissionPoolFilterForm(request.GET or None) + if search_form.is_valid(): + submissions = search_form.search(Submission.objects.all(), request.user) + else: + # Mainly as fallback for the old-pool while in test phase. + submissions = Submission.objects.pool(request.user) + + # submissions = Submission.objects.pool(request.user) + recommendations = EICRecommendation.objects.filter(submission__in=submissions) + recs_to_vote_on = recommendations.user_may_vote_on(request.user) + assignments_to_consider = EditorialAssignment.objects.open().filter(to=request.user.contributor) + + # Forms consider_assignment_form = ConsiderAssignmentForm() - recs_to_vote_on = (EICRecommendation.objects.get_for_user_in_pool(request.user) - .filter(eligible_to_vote=contributor) - .exclude(recommendation__in=[-1, -2]) - .exclude(voted_for=contributor) - .exclude(voted_against=contributor) - .exclude(voted_abstain=contributor) - .exclude(submission__status__in=SUBMISSION_STATUS_VOTING_DEPRECATED)) rec_vote_form = RecommendationVoteForm() remark_form = RemarkForm() context = { - 'submissions_in_pool': submissions_in_pool, + 'submissions': submissions.order_by('status', '-submission_date'), + 'search_form': search_form, 'submission_status': SUBMISSION_STATUS, - 'recommendations_undergoing_voting': recommendations_undergoing_voting, - 'recommendations_to_prepare_for_voting': recommendations_to_prepare_for_voting, + 'recommendations': recommendations, 'assignments_to_consider': assignments_to_consider, 'consider_assignment_form': consider_assignment_form, 'recs_to_vote_on': recs_to_vote_on, 'rec_vote_form': rec_vote_form, 'remark_form': remark_form, - 'submission': None } # The following is in test phase. Update if test is done # -- - # Search - search_form = SubmissionPoolFilterForm(request.GET or None) - if search_form.is_valid(): - context['submissions_in_pool'] = search_form.search(context['submissions_in_pool'], - request.user.contributor) - context['search_form'] = search_form - # Show specific submission in the pool + context['submission'] = None if arxiv_identifier_w_vn_nr: try: - context['submission'] = context['submissions_in_pool'].get( + context['submission'] = Submission.objects.pool_full(request.user).get( arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) except Submission.DoesNotExist: pass # EdColAdmin related variables - if request.user.contributor.is_EdCol_Admin(): + if request.user.has_perm('scipost.can_oversee_refereeing'): context['latest_events'] = SubmissionEvent.objects.for_eic().last_hours() # Temporary test logic: only testers see the new Pool @@ -416,7 +409,7 @@ def submissions_by_status(request, status): if status not in status_dict.keys(): errormessage = 'Unknown status.' return render(request, 'scipost/error.html', {'errormessage': errormessage}) - submissions_of_status = (Submission.objects.get_pool(request.user) + submissions_of_status = (Submission.objects.pool_full(request.user) .filter(status=status).order_by('-submission_date')) context = { @@ -428,13 +421,13 @@ def submissions_by_status(request, status): @login_required -@permission_required('scipost.can_view_pool', raise_exception=True) +# @permission_required('scipost.can_view_pool', raise_exception=True) def add_remark(request, arxiv_identifier_w_vn_nr): """ With this method, an Editorial Fellow or Board Member is adding a remark on a Submission. """ - submission = get_object_or_404(Submission.objects.get_pool(request.user), + submission = get_object_or_404(Submission.objects.pool_editable(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) remark_form = RemarkForm(request.POST or None) @@ -453,7 +446,11 @@ def add_remark(request, arxiv_identifier_w_vn_nr): @login_required @permission_required('scipost.can_assign_submissions', raise_exception=True) def assign_submission(request, arxiv_identifier_w_vn_nr): - submission_to_assign = get_object_or_404(Submission.objects.get_pool(request.user), + """ + Assign Editor-in-charge to Submission. + Action done by SciPost Administration or Editorial College Administration. + """ + submission_to_assign = get_object_or_404(Submission.objects.pool_editable(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) form = AssignSubmissionForm(discipline=submission_to_assign.discipline) context = {'submission_to_assign': submission_to_assign, @@ -464,7 +461,11 @@ def assign_submission(request, arxiv_identifier_w_vn_nr): @login_required @permission_required('scipost.can_assign_submissions', raise_exception=True) def assign_submission_ack(request, arxiv_identifier_w_vn_nr): - submission = get_object_or_404(Submission.objects.get_pool(request.user), + """ + Assign Editor-in-charge to Submission. + Action done by SciPost Administration or Editorial College Administration. + """ + submission = get_object_or_404(Submission.objects.pool_editable(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) if request.method == 'POST': form = AssignSubmissionForm(request.POST, discipline=submission.discipline) @@ -524,7 +525,7 @@ def assignment_request(request, assignment_id): assignment.submission.editor_in_charge = request.user.contributor assignment.submission.open_for_reporting = True deadline = timezone.now() + datetime.timedelta(days=28) # for papers - if assignment.submission.submitted_to_journal == 'SciPost Physics Lecture Notes': + if assignment.submission.submitted_to_journal == 'SciPostPhysLectNotes': deadline += datetime.timedelta(days=28) assignment.submission.reporting_deadline = deadline assignment.submission.open_for_commenting = True @@ -532,9 +533,6 @@ def assignment_request(request, assignment_id): SubmissionUtils.load({'assignment': assignment}) SubmissionUtils.deprecate_other_assignments() - assign_perm('can_take_editorial_actions', request.user, assignment.submission) - ed_admins = Group.objects.get(name='Editorial Administrators') - assign_perm('can_take_editorial_actions', ed_admins, assignment.submission) SubmissionUtils.send_EIC_appointment_email() SubmissionUtils.send_author_prescreening_passed_email() @@ -572,7 +570,7 @@ 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 assignment_request method. """ - submission = get_object_or_404(Submission.objects.get_pool(request.user), + submission = get_object_or_404(Submission.objects.pool(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) errormessage = None if submission.status == 'assignment_failed': @@ -594,7 +592,7 @@ def volunteer_as_EIC(request, arxiv_identifier_w_vn_nr): date_created=timezone.now(), date_answered=timezone.now()) deadline = timezone.now() + datetime.timedelta(days=28) # for papers - if submission.submitted_to_journal == 'SciPost Physics Lecture Notes': + if submission.submitted_to_journal == 'SciPostPhysLectNotes': deadline += datetime.timedelta(days=28) submission.status = 'EICassigned' submission.editor_in_charge = contributor @@ -607,9 +605,6 @@ def volunteer_as_EIC(request, arxiv_identifier_w_vn_nr): 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() SubmissionUtils.send_author_prescreening_passed_email() @@ -630,7 +625,7 @@ def assignment_failed(request, arxiv_identifier_w_vn_nr): The submission is rejected. This method is called from pool.html by an Editorial Administrator. """ - submission = get_object_or_404(Submission.objects.get_pool(request.user), + submission = get_object_or_404(Submission.objects.pool(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) if request.method == 'POST': form = ModifyPersonalMessageForm(request.POST) @@ -670,20 +665,21 @@ def assignments(request): current_assignments = assignments.filter(accepted=True, deprecated=False, completed=False) - consider_assignment_form = ConsiderAssignmentForm() context = { 'assignments_to_consider': assignments_to_consider, - 'consider_assignment_form': consider_assignment_form, 'current_assignments': current_assignments, } - return render(request, 'submissions/assignments.html', context) + return render(request, 'submissions/pool/assignments.html', context) @login_required -@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.objects.filter_editorial_page(request.user), + """ + The central page for the EIC to manage all its Editorial duties. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) context = { @@ -695,11 +691,16 @@ def editorial_page(request, arxiv_identifier_w_vn_nr): @login_required -@permission_required_or_403('can_take_editorial_actions', - (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) def cycle_form_submit(request, arxiv_identifier_w_vn_nr): - submission = get_object_or_404(Submission.objects.get_pool(request.user), + """ + If Submission is `resubmission_incoming` the EIC should first choose what refereeing + cycle to choose. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + form = SubmissionCycleChoiceForm(request.POST or None, instance=submission) if form.is_valid(): submission = form.save() @@ -717,10 +718,13 @@ def cycle_form_submit(request, arxiv_identifier_w_vn_nr): @login_required -@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.objects.filter_editorial_page(request.user), + """ + Select/Invite referees by first listing them here. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) context = {} queryresults = '' @@ -758,8 +762,6 @@ def select_referee(request, arxiv_identifier_w_vn_nr): @login_required -@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): """ @@ -769,9 +771,12 @@ def recruit_referee(request, arxiv_identifier_w_vn_nr): This function emails a registration invitation to this person. The pending refereeing invitation is then recognized upon registration, using the invitation token. + + Accessible for: Editor-in-charge and Editorial Administration """ - submission = get_object_or_404(Submission.objects.filter_editorial_page(request.user), + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), 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(): @@ -820,8 +825,6 @@ def recruit_referee(request, arxiv_identifier_w_vn_nr): @login_required -@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): """ @@ -829,10 +832,13 @@ def send_refereeing_invitation(request, arxiv_identifier_w_vn_nr, contributor_id 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. + + Accessible for: Editor-in-charge and Editorial Administration """ - submission = get_object_or_404(Submission.objects.get_pool(request.user), + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) contributor = get_object_or_404(Contributor, pk=contributor_id) + if not contributor.is_currently_available: errormessage = ('This Contributor is marked as currently unavailable. ' 'Please go back and select another referee.') @@ -865,15 +871,17 @@ def send_refereeing_invitation(request, arxiv_identifier_w_vn_nr, contributor_id @login_required -@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. It can be used for registered as well as unregistered referees. + + Accessible for: Editor-in-charge and Editorial Administration """ - invitation = get_object_or_404(RefereeInvitation, pk=invitation_id) + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + invitation = get_object_or_404(submission.referee_invitations.all(), pk=invitation_id) invitation.nr_reminders += 1 invitation.date_last_reminded = timezone.now() invitation.save() @@ -882,42 +890,50 @@ def ref_invitation_reminder(request, arxiv_identifier_w_vn_nr, invitation_id): SubmissionUtils.send_ref_reminder_email() else: SubmissionUtils.send_unreg_ref_reminder_email() + messages.success(request, 'Reminder sent succesfully.') return redirect(reverse('submissions:editorial_page', kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) @login_required @permission_required('scipost.can_referee', raise_exception=True) -def accept_or_decline_ref_invitations(request): +def accept_or_decline_ref_invitations(request, invitation_id=None): """ RefereeInvitations need to be either accepted or declined by the invited user using this view. The decision will be taken one invitation at a time. """ - invitation = RefereeInvitation.objects.filter(referee__user=request.user, - accepted=None, - cancelled=False).first() + invitation = RefereeInvitation.objects.filter( + referee__user=request.user, accepted=None, cancelled=False) + if invitation_id: + try: + invitation = invitation.get(id=invitation_id) + except RefereeInvitation.DoesNotExist: + invitation = invitation.first() + else: + invitation = invitation.first() + if not invitation: - messages.success(request, 'There are no Refereeing Invitations for you to consider.') + messages.success(request, 'There are no more Refereeing Invitations for you to consider.') return redirect(reverse('scipost:personal_page')) - form = ConsiderRefereeInvitationForm() - context = {'invitation_to_consider': invitation, 'form': form} - return render(request, 'submissions/accept_or_decline_ref_invitations.html', context) - -@login_required -@permission_required('scipost.can_referee', raise_exception=True) -def accept_or_decline_ref_invitation_ack(request, invitation_id): - invitation = get_object_or_404(RefereeInvitation, pk=invitation_id) form = ConsiderRefereeInvitationForm(request.POST or None) if form.is_valid(): invitation.date_responded = timezone.now() if form.cleaned_data['accept'] == 'True': invitation.accepted = True decision_string = 'accepted' + messages.success(request, ('<h3>Thank you for agreeing to referee this Submission</h3>' + '<p>When you are ready, please go to the ' + '<a href="{url}">Submission\'s page</a> to' + ' submit your Report.</p>'.format( + url=invitation.submission.get_absolute_url()))) else: invitation.accepted = False decision_string = 'declined' invitation.refusal_reason = form.cleaned_data['refusal_reason'] + messages.success(request, ('<h1>You have declined to contribute a Report</h1>' + 'Nonetheless, we thank you very much for considering' + ' this refereeing invitation.</p>')) invitation.save() SubmissionUtils.load({'invitation': invitation}, request) SubmissionUtils.email_referee_response_to_EIC() @@ -929,9 +945,13 @@ def accept_or_decline_ref_invitation_ack(request, invitation_id): invitation.submission.add_event_for_eic('Referee %s has %s the refereeing invitation.' % (invitation.referee.user.last_name, decision_string)) - - context = {'invitation': invitation} - return render(request, 'submissions/accept_or_decline_ref_invitation_ack.html', context) + return redirect('submissions:accept_or_decline_ref_invitations') + form = ConsiderRefereeInvitationForm() + context = { + 'invitation': invitation, + 'form': form + } + return render(request, 'submissions/accept_or_decline_ref_invitations.html', context) def decline_ref_invitation(request, invitation_key): @@ -965,15 +985,20 @@ def decline_ref_invitation(request, invitation_key): @login_required -@permission_required_or_403('can_take_editorial_actions', - (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) def cancel_ref_invitation(request, arxiv_identifier_w_vn_nr, invitation_id): """ This method is used by the Editor-in-charge from the editorial_page to remove a referee for the list of invited ones. It can be used for registered as well as unregistered referees. + + Accessible for: Editor-in-charge and Editorial Administration """ - invitation = get_object_or_404(RefereeInvitation, pk=invitation_id) + try: + submissions = Submission.objects.filter_for_eic(request.user) + invitation = submissions.referee_invitations.get(pk=invitation_id) + except RefereeInvitation.DoesNotExist: + raise Http404 + invitation.cancelled = True invitation.save() SubmissionUtils.load({'invitation': invitation}) @@ -989,11 +1014,15 @@ def cancel_ref_invitation(request, arxiv_identifier_w_vn_nr, invitation_id): @login_required -@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.objects.get_pool(request.user), + """ + Extend Refereeing deadline for Submission and open reporting and commenting. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), 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 @@ -1007,10 +1036,14 @@ def extend_refereeing_deadline(request, arxiv_identifier_w_vn_nr, days): @login_required -@permission_required_or_403('can_take_editorial_actions', - (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) def set_refereeing_deadline(request, arxiv_identifier_w_vn_nr): - submission = get_object_or_404(Submission.objects.get_pool(request.user), + """ + Set Refereeing deadline for Submission and open reporting and commenting if + the new date is in the future. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) form = SetRefereeingDeadlineForm(request.POST or None) @@ -1023,12 +1056,7 @@ def set_refereeing_deadline(request, arxiv_identifier_w_vn_nr): submission.latest_activity = timezone.now() submission.save() submission.add_general_event('A new refereeing deadline is set.') - context = {'ack_header': 'New reporting deadline set.', - 'followup_message': 'Return to the ', - 'followup_link': reverse('submissions:editorial_page', - kwargs={'arxiv_identifier_w_vn_nr': submission.arxiv_identifier_w_vn_nr}), - 'followup_link_label': 'Submission\'s Editorial Page'} - return render(request, 'scipost/acknowledgement.html', context) + messages.success(request, 'New reporting deadline set.') else: messages.error(request, 'The deadline has not been set. Please try again.') @@ -1037,8 +1065,6 @@ def set_refereeing_deadline(request, arxiv_identifier_w_vn_nr): @login_required -@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 @@ -1046,9 +1072,12 @@ def close_refereeing_round(request, arxiv_identifier_w_vn_nr): Automatically emails the authors to ask them if they want to round off any replies to reports or comments before the editorial recommendation is formulated. + + Accessible for: Editor-in-charge and Editorial Administration """ - submission = get_object_or_404(Submission.objects.get_pool(request.user), + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + submission.open_for_reporting = False submission.open_for_commenting = False if submission.status == 'EICassigned': # only close if currently undergoing refereeing @@ -1064,10 +1093,12 @@ def close_refereeing_round(request, arxiv_identifier_w_vn_nr): @permission_required('scipost.can_oversee_refereeing', raise_exception=True) def refereeing_overview(request): - submissions_under_refereeing = (Submission.objects.filter(status=STATUS_EIC_ASSIGNED) + submissions_under_refereeing = (Submission.objects + .pool_editable(request.user) + .filter(status=STATUS_EIC_ASSIGNED) .order_by('submission_date')) context = {'submissions_under_refereeing': submissions_under_refereeing} - return render(request, 'submissions/refereeing_overview.html', context) + return render(request, 'submissions/admin/refereeing_overview.html', context) @login_required @@ -1076,13 +1107,14 @@ 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, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + submission = get_object_or_404(Submission.objects.pool_full(request.user), + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) errormessage = None if comtype not in dict(ED_COMM_CHOICES).keys(): errormessage = 'Unknown type of cummunication.' # TODO: Verify that this is requested by an authorized contributor (eic, ref, author) elif (comtype in ['EtoA', 'EtoR', 'EtoS'] and - not request.user.has_perm('can_take_editorial_actions', submission)): + submission.editor_in_charge != request.user.contributor): errormessage = 'Only the Editor-in-charge can perform this action.' elif (comtype in ['AtoE'] and not (request.user.contributor == submission.submitted_by)): @@ -1095,8 +1127,8 @@ def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): not request.user.groups.filter(name='Editorial Administrators').exists()): errormessage = 'Only Editorial Administrators can perform this action.' if errormessage is not None: - context = {'errormessage': errormessage, 'comtype': comtype} - return render(request, 'submissions/communication.html', context) + messages.warning(request, errormessage) + return redirect(reverse('submissions:pool')) form = EditorialCommunicationForm(request.POST or None) if form.is_valid(): @@ -1122,13 +1154,17 @@ def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): @login_required -@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.objects.filter_editorial_page(request.user), + """ + Write EIC Recommendation. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) - if submission.eic_recommendation_required(): + + if not submission.eic_recommendation_required: messages.warning(request, ('<h3>An Editorial Recommendation is not required</h3>' 'This submission\'s current status is: <em>%s</em>' % submission.get_status_display())) @@ -1137,11 +1173,13 @@ def eic_recommendation(request, arxiv_identifier_w_vn_nr): # Find EditorialAssignment for user try: - assignment = submission.editorial_assignments.get(submission=submission, - to=request.user.contributor) + assignment = submission.editorial_assignments.accepted().get( + to=submission.editor_in_charge) except EditorialAssignment.DoesNotExist: messages.warning(request, ('You cannot formulate an Editorial Recommendation,' - ' because you are not assigned as editor-in-charge.')) + ' because the Editorial Assignment has not been set properly.' + ' Please ' + '<a href="mailto:admin@scipost.org">report the problem</a>.')) return redirect(reverse('submissions:editorial_page', args=[submission.arxiv_identifier_w_vn_nr])) @@ -1189,7 +1227,7 @@ def eic_recommendation(request, arxiv_identifier_w_vn_nr): context = {'submission': submission, 'form': form} - return render(request, 'submissions/eic_recommendation.html', context) + return render(request, 'submissions/pool/recommendation_formulate.html', context) ########### @@ -1264,10 +1302,6 @@ def submit_report(request, arxiv_identifier_w_vn_nr): SubmissionUtils.email_EIC_report_delivered() SubmissionUtils.email_referee_report_delivered() - # Assign explicit permission to EIC to vet this report - assign_perm('submissions.can_vet_submitted_reports', submission.editor_in_charge.user, - newreport) - # Add SubmissionEvents for the EIC only, as it can also be rejected still submission.add_event_for_eic('%s has submitted a new Report.' % request.user.last_name) @@ -1280,12 +1314,13 @@ def submit_report(request, arxiv_identifier_w_vn_nr): @login_required -@permission_required('submissions.can_vet_submitted_reports', raise_exception=True) def vet_submitted_reports_list(request): """ Reports with status `unvetted` will be shown (oldest first). """ - reports_to_vet = Report.objects.awaiting_vetting().order_by('date_submitted') + submissions = get_list_or_404(Submission.objects.filter_for_eic(request.user)) + reports_to_vet = Report.objects.filter( + submission__in=submissions).awaiting_vetting().order_by('date_submitted') context = {'reports_to_vet': reports_to_vet} return render(request, 'submissions/vet_submitted_reports_list.html', context) @@ -1300,11 +1335,9 @@ def vet_submitted_report(request, report_id): After vetting an email is sent to the report author, bcc EIC. If report has not been refused, the submission author is also mailed. """ - # Method `get_objects_for_user` gets all Reports that are assigned to the user - # or *all* Reports if user is SciPost Admin or Vetting Editor. - report = get_object_or_404((get_objects_for_user(request.user, - 'submissions.can_vet_submitted_reports') - .awaiting_vetting()), id=report_id) + submissions = Submission.objects.filter_for_eic(request.user) + report = get_object_or_404(Report.objects.filter( + submission__in=submissions).awaiting_vetting(), id=report_id) form = VetReportForm(request.POST or None, initial={'report': report}) if form.is_valid(): @@ -1339,72 +1372,65 @@ def vet_submitted_report(request, report_id): return render(request, 'submissions/vet_submitted_report.html', context) +@login_required @permission_required('scipost.can_prepare_recommendations_for_voting', raise_exception=True) @transaction.atomic def prepare_for_voting(request, rec_id): - recommendation = get_object_or_404((EICRecommendation.objects - .get_for_user_in_pool(request.user)), id=rec_id) - Fellows_with_expertise = Contributor.objects.filter( - user__groups__name__in=['Editorial College'], - expertises__contains=[recommendation.submission.subject_area]) + submissions = Submission.objects.pool_editable(request.user) + recommendation = get_object_or_404( + EICRecommendation.objects.filter(submission__in=submissions), id=rec_id) + + fellows_with_expertise = recommendation.submission.fellows.filter( + contributor__expertises__contains=[recommendation.submission.subject_area]) + coauthorships = {} - if request.method == 'POST': - eligibility_form = VotingEligibilityForm( - request.POST, - discipline=recommendation.submission.discipline, - subject_area=recommendation.submission.subject_area - ) - if eligibility_form.is_valid(): - recommendation.eligible_to_vote = eligibility_form.cleaned_data['eligible_Fellows'] - recommendation.voted_for.add(recommendation.submission.editor_in_charge) - recommendation.save() - recommendation.submission.status = 'put_to_EC_voting' - recommendation.submission.save() - messages.success(request, 'We have registered your selection.') - # Add SubmissionEvents - recommendation.submission.add_event_for_eic('The Editorial Recommendation has been ' - 'put forward to the College for voting.') + eligibility_form = VotingEligibilityForm(request.POST or None, instance=recommendation) + if eligibility_form.is_valid(): + eligibility_form.save() + messages.success(request, 'We have registered your selection.') - return redirect(reverse('submissions:editorial_page', - args=[recommendation.submission.arxiv_identifier_w_vn_nr])) + # Add SubmissionEvents + recommendation.submission.add_event_for_eic('The Editorial Recommendation has been ' + 'put forward to the College for voting.') + + return redirect(reverse('submissions:editorial_page', + args=[recommendation.submission.arxiv_identifier_w_vn_nr])) else: # Identify possible co-authorships in last 3 years, disqualifying Fellow from voting: if recommendation.submission.metadata is not None: - for Fellow in Fellows_with_expertise: + for fellow in fellows_with_expertise: sub_auth_boolean_str = '((' + (recommendation.submission .metadata['entries'][0]['authors'][0]['name'] .split()[-1]) for author in recommendation.submission.metadata['entries'][0]['authors'][1:]: sub_auth_boolean_str += '+OR+' + author['name'].split()[-1] sub_auth_boolean_str += ')+AND+' - search_str = sub_auth_boolean_str + Fellow.user.last_name + ')' + search_str = sub_auth_boolean_str + fellow.contributor.user.last_name + ')' queryurl = ('http://export.arxiv.org/api/query?search_query=au:%s' % search_str + '&sortBy=submittedDate&sortOrder=descending' '&max_results=5') arxivquery = feedparser.parse(queryurl) queryresults = arxivquery if queryresults.entries: - coauthorships[Fellow.user.last_name] = queryresults - - eligibility_form = VotingEligibilityForm( - discipline=recommendation.submission.discipline, - subject_area=recommendation.submission.subject_area) + coauthorships[fellow.contributor.user.last_name] = queryresults context = { 'recommendation': recommendation, - 'Fellows_with_expertise': Fellows_with_expertise, + 'fellows_with_expertise': fellows_with_expertise, 'coauthorships': coauthorships, 'eligibility_form': eligibility_form, } - return render(request, 'submissions/prepare_for_voting.html', context) + return render(request, 'submissions/admin/recommendation_prepare_for_voting.html', context) -@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True) +@login_required @transaction.atomic def vote_on_rec(request, rec_id): - recommendation = get_object_or_404((EICRecommendation.objects - .get_for_user_in_pool(request.user)), id=rec_id) + submissions = Submission.objects.pool_editable(request.user) + recommendation = get_object_or_404( + EICRecommendation.objects.filter(submission__in=submissions), id=rec_id) + form = RecommendationVoteForm(request.POST or None) if form.is_valid(): if form.cleaned_data['vote'] == 'agree': @@ -1453,13 +1479,15 @@ def remind_Fellows_to_vote(request): """ This method sends an email to all Fellow with pending voting duties. It must be called by and Editorial Administrator. + + TODO: This reminder function doesn't filter per submission?! """ - recommendations_undergoing_voting = (EICRecommendation.objects - .get_for_user_in_pool(request.user) - .filter(submission__status__in=['put_to_EC_voting'])) + submissions = Submission.objects.pool_editable(request.user) + recommendations = EICRecommendation.objects.filter(submission__in=submissions).put_to_voting() + Fellow_emails = [] Fellow_names = [] - for rec in recommendations_undergoing_voting: + for rec in recommendations: for Fellow in rec.eligible_to_vote.all(): if (Fellow not in rec.voted_for.all() and Fellow not in rec.voted_against.all() @@ -1487,10 +1515,15 @@ def fix_College_decision(request, rec_id): Terminates the voting on a Recommendation. Called by an Editorial Administrator. + # TODO - 2 bugs: + TO FIX: If multiple recommendations are submitted; decisions may be overruled unexpectedly. + TO FIX: A college decision can be fixed multiple times, there is no already-fixed mechanism!!! """ - recommendation = get_object_or_404((EICRecommendation.objects - .get_for_user_in_pool(request.user)), pk=rec_id) + submissions = Submission.objects.pool_full(request.user) + recommendation = get_object_or_404(EICRecommendation.objects.filter( + submission__in=submissions), id=rec_id) + submission = recommendation.submission if recommendation.recommendation in [1, 2, 3]: # Publish as Tier I, II or III @@ -1535,7 +1568,7 @@ def fix_College_decision(request, rec_id): class EICRecommendationView(SubmissionAdminViewMixin, DetailView): permission_required = 'scipost.can_fix_College_decision' - template_name = 'submissions/admin/eic_recommendation_detail.html' + template_name = 'submissions/admin/recommendation.html' editorial_page = True def get_context_data(self, *args, **kwargs): @@ -1570,14 +1603,3 @@ class PlagiarismReportPDFView(SubmissionAdminViewMixin, SingleObjectMixin, Redir if not url: raise Http404 return url - - -class AdminRecommendationView(SubmissionAdminViewMixin, DetailView): - permission_required = 'scipost.can_fix_College_decision' - template_name = 'submissions/admin/recommendation.html' - editorial_page = True - - def get_object(self): - """ Get the EICRecommendation as a submission-related instance. """ - submission = super().get_object() - return submission.eicrecommendations.first() diff --git a/templates/partials/pagination.html b/templates/partials/pagination.html new file mode 100644 index 0000000000000000000000000000000000000000..28924103800f75c6f1e860c481ffe9ada73ca353 --- /dev/null +++ b/templates/partials/pagination.html @@ -0,0 +1,28 @@ +{% load request_filters %} + +<div class="text-center"> + {% if page_obj.has_previous %} + <a class="" href="?{% url_replace page=page_obj.previous_page_number %}"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</a> + {% else %} + <span class="text-muted"><i class="fa fa-long-arrow-left" aria-hidden="true"></i> Previous</span> + {% endif %} + + + {% for page in page_obj.pages %} + {% if page %} + {% if page == page_obj.number %} + <span class="current page">{{ page }}</span> + {% else %} + <a href="?{% url_replace page=page %}" class="page">{{ page }}</a> + {% endif %} + {% else %} + ... + {% endif %} + {% endfor %} + + {% if page_obj.has_next %} + <a class="" href="?{% url_replace page=page_obj.next_page_number %}">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></a> + {% else %} + <span class="text-muted">Next <i class="fa fa-long-arrow-right" aria-hidden="true"></i></span> + {% endif %} +</div> diff --git a/theses/templates/theses/thesislink_list.html b/theses/templates/theses/thesislink_list.html index d2dd2e2e0cde33324b2812749a0d14e23905d649..0e417c3656c7a5f784afd6f3172d5f58c014efc2 100644 --- a/theses/templates/theses/thesislink_list.html +++ b/theses/templates/theses/thesislink_list.html @@ -53,34 +53,28 @@ {% else %} <h2>Search results:</h3> {% endif %} - - {% if object_list %} - {% if is_paginated %} - <p> - {% if page_obj.has_previous %} - <a href="?{% url_replace page=page_obj.previous_page_number %}">Previous</a> - {% endif %} - Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. - {% if page_obj.has_next %} - <a href="?{% url_replace page=page_obj.next_page_number %}">Next</a> - {% endif %} - </p> - {% endif %} - - </div> - <div class="col-12"> - - <ul class="list-group list-group-flush"> - {% for thesislink in object_list %} - <li class="list-group-item"> - {% include 'theses/_thesislink_card_content.html' with thesislink=thesislink %} - </li> - {% endfor %} - </ul> - {% else %} - <h3>No match found for your search query.</h3> - {% endif %} </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for thesislink in object_list %} + <li class="list-group-item"> + {% include 'theses/_thesislink_card_content.html' with thesislink=thesislink %} + </li> + {% empty %} + <h3><em>No match found for your search query.</em></h3> + {% endfor %} + </ul> + </div> + {% if is_paginated %} + <div class="col-12"> + {% include 'partials/pagination.html' with page_obj=page_obj %} + </div> + {% endif %} </div> {% endblock content %} diff --git a/theses/templates/theses/vet_thesislink.html b/theses/templates/theses/vet_thesislink.html index 30b1bb1831560e02be8b702764931b10ddff418f..f3124effdbcdec6f4ba58725a329426ca713fda7 100644 --- a/theses/templates/theses/vet_thesislink.html +++ b/theses/templates/theses/vet_thesislink.html @@ -1,7 +1,13 @@ -{% extends 'scipost/base.html' %} +{% extends 'scipost/_personal_page_base.html' %} {% load bootstrap %} +{% block breadcrumb_items %} + {{block.super}} + <a href="{% url 'theses:unvetted_thesislinks' %}" class="breadcrumb-item">Unvetted Thesis Links</a> + <span class="breadcrumb-item">Vet {{ form.instance.title }} by {{ form.instance.author }}</span> +{% endblock %} + {% block pagetitle %}: Unvetted Thesis Links{% endblock pagetitle %} {% block content %} diff --git a/theses/views.py b/theses/views.py index 285bda18f792efc3f376a78938a548b562825a71..1bf37ce05b79a2fe4cdbbf6269fe051eb4b40c8c 100644 --- a/theses/views.py +++ b/theses/views.py @@ -14,6 +14,7 @@ from .models import ThesisLink from .forms import RequestThesisLinkForm, ThesisLinkSearchForm, VetThesisLinkForm from comments.forms import CommentForm +from scipost.mixins import PaginationMixin import strings @@ -78,7 +79,7 @@ class VetThesisLink(UpdateView): return HttpResponseRedirect(self.get_success_url()) -class ThesisListView(ListView): +class ThesisListView(PaginationMixin, ListView): model = ThesisLink form = ThesisLinkSearchForm paginate_by = 10