diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py index 0ca208465dd5f4706ee6a3421d8bb91d4eee9e0c..05df150ab0683d6a9aa9999c7ec7d6f716d1fff5 100644 --- a/SciPost_v1/settings/base.py +++ b/SciPost_v1/settings/base.py @@ -276,6 +276,8 @@ JOURNALS_DIR = 'journals' CROSSREF_LOGIN_ID = '' CROSSREF_LOGIN_PASSWORD = '' +CROSSREF_DEBUG = True +CROSSREF_DEPOSIT_EMAIL = 'techsupport@scipost.org' DOAJ_API_KEY = '' # Google reCaptcha with Google's global test keys @@ -313,3 +315,42 @@ AUTH_PASSWORD_VALIDATORS = [ ] CSRF_FAILURE_VIEW = 'scipost.views.csrf_failure' + +# Logging +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '[%(asctime)s] %(levelname)s | %(message)s' + }, + }, + 'handlers': { + 'scipost_file_arxiv': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'filename': '/path/to/logs/arxiv.log', + 'formatter': 'verbose', + }, + 'scipost_file_doi': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'filename': '/path/to/logs/doi.log', + 'formatter': 'verbose', + }, + }, + 'loggers': { + 'scipost.services.arxiv': { + 'handlers': ['scipost_file_arxiv'], + 'level': 'INFO', + 'propagate': True, + 'formatter': 'simple', + }, + 'scipost.services.doi': { + 'handlers': ['scipost_file_doi'], + 'level': 'INFO', + 'propagate': True, + 'formatter': 'simple', + }, + }, +} diff --git a/SciPost_v1/settings/local_JSC.py b/SciPost_v1/settings/local_JSC.py index f4dcbe1891cd9a9b8ba42739749f2528e168a2f0..14b06d9ab44773b41532eee5147490c1cc7deb22 100644 --- a/SciPost_v1/settings/local_JSC.py +++ b/SciPost_v1/settings/local_JSC.py @@ -11,3 +11,8 @@ WEBPACK_LOADER['DEFAULT']['BUNDLE_DIR_NAME'] =\ MAILCHIMP_API_USER = get_secret("MAILCHIMP_API_USER") MAILCHIMP_API_KEY = get_secret("MAILCHIMP_API_KEY") + +# Logging +LOGGING['handlers']['scipost_file_arxiv']['filename'] = '/Users/jscaux/Sites/SciPost.org/scipost_v1/local_files/logs/arxiv.log' +LOGGING['handlers']['scipost_file_doi']['filename'] = '/Users/jscaux/Sites/SciPost.org/scipost_v1/local_files/logs/doi.log' +CROSSREF_DEPOSIT_EMAIL = 'jscaux@scipost.org' diff --git a/SciPost_v1/settings/local_jorran.py b/SciPost_v1/settings/local_jorran.py index cd2ed99b46436673da26e9b69da2ec69da258b0d..0ca80ebb49d60854a148e3619d6d79bae6e0d078 100644 --- a/SciPost_v1/settings/local_jorran.py +++ b/SciPost_v1/settings/local_jorran.py @@ -26,3 +26,12 @@ DATABASES['default']['PORT'] = '5433' # iThenticate ITHENTICATE_USERNAME = get_secret('ITHENTICATE_USERNAME') ITHENTICATE_PASSWORD = get_secret('ITHENTICATE_PASSWORD') + +# Logging +LOGGING['handlers']['scipost_file_arxiv']['filename'] = '/Users/jorranwit/Develop/SciPost/SciPost_v1/logs/arxiv.log' +LOGGING['handlers']['scipost_file_doi']['filename'] = '/Users/jorranwit/Develop/SciPost/SciPost_v1/logs/doi.log' + +# Other +CROSSREF_LOGIN_ID = get_secret("CROSSREF_LOGIN_ID") +CROSSREF_LOGIN_PASSWORD = get_secret("CROSSREF_LOGIN_PASSWORD") +CROSSREF_DEPOSIT_EMAIL = 'jorrandewit@scipost.org' diff --git a/SciPost_v1/settings/production.py b/SciPost_v1/settings/production.py index ffba29aff8e844946a5124210c21372395a849c5..0b17f6fed8f94416e5f98d6117b838beda9c3820 100644 --- a/SciPost_v1/settings/production.py +++ b/SciPost_v1/settings/production.py @@ -36,6 +36,9 @@ SERVER_EMAIL = get_secret("SERVER_EMAIL") # Other CROSSREF_LOGIN_ID = get_secret("CROSSREF_LOGIN_ID") CROSSREF_LOGIN_PASSWORD = get_secret("CROSSREF_LOGIN_PASSWORD") +CROSSREF_DEBUG = False +CROSSREF_DEPOSIT_EMAIL = 'admin@scipost.org' + DOAJ_API_KEY = get_secret("DOAJ_API_KEY") HAYSTACK_CONNECTIONS['default']['PATH'] = '/home/scipost/webapps/scipost/SciPost_v1/whoosh_index' MAILCHIMP_API_USER = get_secret("MAILCHIMP_API_USER") @@ -44,3 +47,7 @@ MAILCHIMP_API_KEY = get_secret("MAILCHIMP_API_KEY") # iThenticate ITHENTICATE_USERNAME = get_secret('ITHENTICATE_USERNAME') ITHENTICATE_PASSWORD = get_secret('ITHENTICATE_PASSWORD') + +# Logging +LOGGING['handlers']['scipost_file_arxiv']['filename'] = '/home/scipost/webapps/scipost/logs/arxiv.log' +LOGGING['handlers']['scipost_file_doi']['filename'] = '/home/scipost/webapps/scipost/logs/doi.log' diff --git a/SciPost_v1/settings/staging_release.py b/SciPost_v1/settings/staging_release.py index a9290b92b0524e7a61c13d6322275fcd9d6dfe4f..bef469d83c25b8e9418898747d2057fa002aa0fd 100644 --- a/SciPost_v1/settings/staging_release.py +++ b/SciPost_v1/settings/staging_release.py @@ -20,5 +20,6 @@ MEDIA_ROOT = '/home/jdewit/webapps/scipost_media/' WEBPACK_LOADER['DEFAULT']['CACHE'] = True WEBPACK_LOADER['DEFAULT']['BUNDLE_DIR_NAME'] = '/home/jdewit/webapps/scipost_static/bundles/' -# Error reporting -ADMINS = MANAGERS = (('J. de Wit', 'jorrandewit@outlook.com'), ) +# Logging +LOGGING['handlers']['scipost_file_arxiv']['filename'] = '/home/jdewit/webapps/scipost/logs/arxiv.log' +LOGGING['handlers']['scipost_file_doi']['filename'] = '/home/jdewit/webapps/scipost/logs/doi.log' diff --git a/commentaries/templates/commentaries/commentary_detail.html b/commentaries/templates/commentaries/commentary_detail.html index 4d0160aa6a71bb8447f9fcb3fd1aed472e771f25..710c058dba581f1db8c6edccfc684991f0f0838e 100644 --- a/commentaries/templates/commentaries/commentary_detail.html +++ b/commentaries/templates/commentaries/commentary_detail.html @@ -21,7 +21,10 @@ <h3>Abstract:</h3> <p>{{ commentary.pub_abstract }}</p> -{% include 'scipost/comments_block.html' with comments=commentary.comments.vetted type_of_object='Commentary' %} +{% if commentary.comments.vetted %} + <hr class="divider"> + {% include 'scipost/comments_block.html' with comments=commentary.comments.vetted type_of_object='Commentary' %} +{% endif %} {% include 'comments/new_comment.html' with object_id=commentary.id type_of_object='commentary' open_for_commenting=commentary.open_for_commenting %} diff --git a/commentaries/templates/commentaries/howto.html b/commentaries/templates/commentaries/howto.html index eb2cc763336eefd9d600790b906b19dc3f2249b5..f1e3d42d18ef95d2377ec6423010e1a4c9f536c0 100644 --- a/commentaries/templates/commentaries/howto.html +++ b/commentaries/templates/commentaries/howto.html @@ -2,17 +2,16 @@ {% block pagetitle %}: Commentaries{% endblock pagetitle %} -{% block headsup %} - <script type="text/javascript" async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML"></script> -{% endblock headsup %} +{% block breadcrumb %} + <div class="container-outside header"> + <div class="container"> + <h1>SciPost Commentaries how-to</h1> + </div> + </div> +{% endblock %} {% block content %} -<div class="row"> - <div class="col-12"> - <h1 class="highlight">SciPost Commentaries how-to</h1> - </div> -</div> <div class="row"> <div class="col-12"> <h2>Activation procedure</h2> diff --git a/comments/models.py b/comments/models.py index 5410c48ffe73fc3ae9b174b69216fc497bb964e3..e138ca39ad2b9a7fefc8d3f7606207bdfc176df5 100644 --- a/comments/models.py +++ b/comments/models.py @@ -10,6 +10,7 @@ from guardian.shortcuts import assign_perm from scipost.behaviors import TimeStampedModel from scipost.models import Contributor +from commentaries.constants import COMMENTARY_PUBLISHED from .behaviors import validate_file_extension, validate_max_file_size from .constants import COMMENT_STATUS, STATUS_PENDING @@ -188,3 +189,64 @@ class Comment(TimeStampedModel): self.nr_N = self.in_notsure.count() self.nr_D = self.in_disagreement.count() self.save() + + @property + def relation_to_published(self): + """ + Check if the Comment relates to a SciPost-published object. + If it is, return a dict with info on relation to the published object, + based on Crossref's peer review content type. + """ + # Import here due to circular import errors + from submissions.models import Submission + from journals.models import Publication + from commentaries.models import Commentary + + to_object = self.core_content_object + if isinstance(to_object, Submission): + publication = Publication.objects.filter( + accepted_submission__arxiv_identifier_wo_vn_nr=to_object.arxiv_identifier_wo_vn_nr) + if publication: + relation = { + 'isReviewOfDOI': publication.doi_string, + 'stage': 'pre-publication', + 'title': 'Comment on ' + to_object.arxiv_identifier_w_vn_nr, + } + if self.is_author_reply: + relation['type'] = 'author-comment' + else: + relation['type'] = 'community-comment' + return relation + if isinstance(to_object, Commentary): + if to_object.type == COMMENTARY_PUBLISHED: + relation = { + 'isReviewOfDOI': to_object.pub_doi, + 'stage': 'post-publication', + 'title': 'Comment on ' + to_object.pub_doi, + } + if self.is_author_reply: + relation['type'] = 'author-comment' + relation['contributor_role'] = 'author' + else: + relation['type'] = 'community-comment' + relation['contributor_role'] = 'reviewer-external' + return relation + + return None + + @property + def citation(self): + citation = '' + if self.doi_string: + if self.anonymous: + citation += 'Anonymous, ' + else: + citation += '%s %s, ' % (self.author.user.first_name, self.author.user.last_name) + + if self.is_author_reply: + citation += 'SciPost Author Replies, ' + else: + citation += 'SciPost Comments, ' + citation += 'Delivered %s, ' % self.date_submitted.strftime('%Y-%m-%d') + citation += 'doi: %s' % self.doi_string + return citation diff --git a/comments/templates/comments/_comment_identifier.html b/comments/templates/comments/_comment_identifier.html index 2d518ecedeea4fe7dd83cdf87755bd40e115d019..5eb681610a2fd2e657a5d71fcea0a9d1656e16f3 100644 --- a/comments/templates/comments/_comment_identifier.html +++ b/comments/templates/comments/_comment_identifier.html @@ -17,7 +17,7 @@ <a href="{{comment.author.get_absolute_url}}">{{comment.author.user.first_name}} {{comment.author.user.last_name}}</a> on {{comment.date_submitted|date:'Y-m-d'}} {% endif %} - {% if comment.doi_string %} <small>doi: {{ comment.doi_string }}</small>{% endif %} + {% if comment.doi_string %} <small>{{ comment|citation }}</small>{% endif %} </h3> diff --git a/general.py b/general.py new file mode 100644 index 0000000000000000000000000000000000000000..5570b662718dd4458c5d43ddd33f02efb8df178d --- /dev/null +++ b/general.py @@ -0,0 +1,110 @@ +from django.conf.urls import url +from django.urls import reverse_lazy +from django.views.generic import TemplateView, RedirectView + +from journals import views as journals_views + +urlpatterns = [ + # Journals + url(r'^$', journals_views.journals, name='journals'), + url(r'scipost_physics', RedirectView.as_view(url=reverse_lazy('scipost:landing_page', + args=['SciPostPhys']))), + url(r'^journals_terms_and_conditions$', + TemplateView.as_view(template_name='journals/journals_terms_and_conditions.html'), + name='journals_terms_and_conditions'), + url(r'^crossmark_policy$', + TemplateView.as_view(template_name='journals/crossmark_policy.html'), + name='crossmark_policy'), + + # Editorial and Administrative Workflow + url(r'^initiate_publication$', + journals_views.initiate_publication, + name='initiate_publication'), + url(r'^validate_publication$', + journals_views.validate_publication, + name='validate_publication'), + url(r'^mark_first_author/(?P<publication_id>[0-9]+)/(?P<contributor_id>[0-9]+)$', + journals_views.mark_first_author, + name='mark_first_author'), + url(r'^mark_first_author_unregistered/(?P<publication_id>[0-9]+)/(?P<unregistered_author_id>[0-9]+)$', + journals_views.mark_first_author_unregistered, + name='mark_first_author_unregistered'), + url(r'^add_author/(?P<publication_id>[0-9]+)/(?P<contributor_id>[0-9]+)$', + journals_views.add_author, + name='add_author'), + url(r'^add_author/(?P<publication_id>[0-9]+)$', + journals_views.add_author, + name='add_author'), + url(r'^add_unregistered_author/(?P<publication_id>[0-9]+)/(?P<unregistered_author_id>[0-9]+)$', + journals_views.add_unregistered_author, + name='add_unregistered_author'), + url(r'^add_new_unreg_author/(?P<publication_id>[0-9]+)$', + journals_views.add_new_unreg_author, + name='add_new_unreg_author'), + url(r'^manage_metadata/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.manage_metadata, + name='manage_metadata'), + url(r'^manage_metadata/(?P<issue_doi_label>[a-zA-Z]+.[0-9]+.[0-9]+)$', + journals_views.manage_metadata, + name='manage_metadata'), + url(r'^manage_metadata/$', + journals_views.manage_metadata, + name='manage_metadata'), + url(r'^create_citation_list_metadata/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.create_citation_list_metadata, + name='create_citation_list_metadata'), + url(r'^create_funding_info_metadata/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.create_funding_info_metadata, + name='create_funding_info_metadata'), + url(r'^add_associated_grant/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.add_associated_grant, + name='add_associated_grant'), + url(r'^add_generic_funder/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.add_generic_funder, + name='add_generic_funder'), + url(r'^create_metadata_xml/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.create_metadata_xml, + name='create_metadata_xml'), + url(r'^metadata_xml_deposit/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})/(?P<option>[a-z]+)$', + journals_views.metadata_xml_deposit, + name='metadata_xml_deposit'), + url(r'^mark_deposit_success/(?P<deposit_id>[0-9]+)/(?P<success>[0-1])$', + journals_views.mark_deposit_success, + name='mark_deposit_success'), + url(r'^produce_metadata_DOAJ/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.produce_metadata_DOAJ, + name='produce_metadata_DOAJ'), + url(r'^metadata_DOAJ_deposit/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.metadata_DOAJ_deposit, + name='metadata_DOAJ_deposit'), + url(r'^mark_doaj_deposit_success/(?P<deposit_id>[0-9]+)/(?P<success>[0-1])$', + journals_views.mark_doaj_deposit_success, + name='mark_doaj_deposit_success'), + url(r'^harvest_citedby_list/$', + journals_views.harvest_citedby_list, + name='harvest_citedby_list'), + url(r'^harvest_citedby_links/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.harvest_citedby_links, + name='harvest_citedby_links'), + url(r'^sign_existing_report/(?P<report_id>[0-9]+)$', + journals_views.sign_existing_report, + name='sign_existing_report'), + url(r'^manage_report_metadata/$', + journals_views.manage_report_metadata, + name='manage_report_metadata'), + url(r'^manage_comment_metadata/$', + journals_views.manage_comment_metadata, + name='manage_comment_metadata'), + url(r'^mark_report_doi_needed/(?P<report_id>[0-9]+)/(?P<needed>[0-1])$', + journals_views.mark_report_doi_needed, + name='mark_report_doi_needed'), + url(r'^mark_comment_doi_needed/(?P<comment_id>[0-9]+)/(?P<needed>[0-1])$', + journals_views.mark_comment_doi_needed, + name='mark_comment_doi_needed'), + url(r'^generic_metadata_xml_deposit/(?P<type_of_object>[a-z]+)/(?P<object_id>[0-9]+)$', + journals_views.generic_metadata_xml_deposit, + name='generic_metadata_xml_deposit'), + url(r'^mark_generic_deposit_success/(?P<deposit_id>[0-9]+)/(?P<success>[0-1])$', + journals_views.mark_generic_deposit_success, + name='mark_generic_deposit_success'), +] diff --git a/journals/admin.py b/journals/admin.py index 2604c736d9db910ab2f5c6e3e02d7db920613359..1011ffaea461237dfb56b9a384b174c7d80d64da 100644 --- a/journals/admin.py +++ b/journals/admin.py @@ -2,11 +2,13 @@ from django.contrib import admin, messages from django import forms from journals.models import UnregisteredAuthor, Journal, Volume, Issue, Publication, \ - Deposit, DOAJDeposit, GenericDOIDeposit + Deposit, DOAJDeposit, GenericDOIDeposit, Reference from scipost.models import Contributor from submissions.models import Submission +admin.site.register(Reference) + class UnregisteredAuthorAdmin(admin.ModelAdmin): search_fields = ['last_name'] diff --git a/journals/forms.py b/journals/forms.py index 3883c6af3ad372e3489770a8ea5b00f3cfe6e822..12ec2553258242d43497e4b735ba05d325ccb7ad 100644 --- a/journals/forms.py +++ b/journals/forms.py @@ -1,10 +1,14 @@ import re +from datetime import datetime + from django import forms +from django.forms import BaseModelFormSet, modelformset_factory from django.utils import timezone -from .models import UnregisteredAuthor, Issue, Publication +from .models import UnregisteredAuthor, Issue, Publication, Reference +from scipost.services import DOICaller from submissions.models import Submission @@ -77,3 +81,96 @@ class CreateMetadataXMLForm(forms.ModelForm): 'rows': 50, 'cols': 50 }) + + +class BaseReferenceFormSet(BaseModelFormSet): + """ + BaseReferenceFormSet is used to help fill the Reference list for Publications + + It is required to add the required keyword argument `publication` to this FormSet. + """ + initial_references = [] + + def __init__(self, *args, **kwargs): + self.publication = kwargs.pop('publication') + extra = kwargs.pop('extra') + self.extra = int(extra if extra else '0') + kwargs['form_kwargs'] = {'publication': self.publication} + super().__init__(*args, **kwargs) + + def prefill(self): + citations = self.publication.metadata.get('citation_list', []) + + for cite in citations: + caller = DOICaller(cite['doi']) + + if caller.is_valid: + # Authors + author_list = [] + for author in caller._crossref_data['author'][:3]: + try: + author_list.append('{}. {}'.format(author['given'][0], author['family'])) + except KeyError: + author_list.append(author['name']) + + if len(author_list) > 3: + authors = author_list[0] + ' et al.' + elif len(author_list) == 3: + authors = '{}, {} and {}'.format( + author_list[0], author_list[1], author_list[2]) + else: + authors = ' and '.join(author_list) + + # Citation + citation = '{} <b>{}</b>, {} ({})'.format( + caller.data['journal'], + caller.data['volume'], + caller.data['pages'], + datetime.strptime(caller.data['pub_date'], '%Y-%m-%d').year) + + self.initial_references.append({ + 'reference_number': cite['key'][3:], + 'authors': authors, + 'title': caller.data['title'], + 'citation': citation, + 'vor': cite['doi'], + 'vor_url': 'https://doi.org/{}'.format(cite['doi']), + }) + else: + self.initial_references.append({ + 'reference_number': cite['key'][3:], + 'vor': cite['doi'], + 'vor_url': 'https://doi.org/{}'.format(cite['doi']), + }) + + # Add prefill information to the form + if not self.initial_extra: + self.initial_extra = self.initial_references + else: + self.initial_extra.extend(self.initial_references) + self.extra += len(self.initial_extra) + + +class ReferenceForm(forms.ModelForm): + class Meta: + model = Reference + fields = [ + 'reference_number', + 'authors', + 'title', + 'citation', + 'vor', + 'vor_url', + ] + + def __init__(self, *args, **kwargs): + self.publication = kwargs.pop('publication') + super().__init__(*args, **kwargs) + + def save(self, *args, **kwargs): + self.instance.publication = self.publication + super().save(*args, **kwargs) + + +ReferenceFormSet = modelformset_factory(Reference, formset=BaseReferenceFormSet, + form=ReferenceForm, can_delete=True) diff --git a/journals/migrations/0003_auto_20180117_2323.py b/journals/migrations/0003_auto_20180117_2323.py new file mode 100644 index 0000000000000000000000000000000000000000..5020b0dab1564a5cd8d66e0949cf841480621828 --- /dev/null +++ b/journals/migrations/0003_auto_20180117_2323.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-17 22:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('journals', '0002_auto_20171229_1435'), + ] + + operations = [ + migrations.AlterField( + model_name='deposit', + name='doi_batch_id', + field=models.CharField(max_length=40), + ), + migrations.AlterField( + model_name='deposit', + name='metadata_xml', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + migrations.AlterField( + model_name='deposit', + name='response_text', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + migrations.AlterField( + model_name='deposit', + name='timestamp', + field=models.CharField(max_length=40), + ), + ] diff --git a/journals/migrations/0004_auto_20180121_1202.py b/journals/migrations/0004_auto_20180121_1202.py new file mode 100644 index 0000000000000000000000000000000000000000..141a392ff3128ccded9d2c857ccf8f8d7d1f30be --- /dev/null +++ b/journals/migrations/0004_auto_20180121_1202.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-21 11:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('journals', '0003_auto_20180117_2323'), + ] + + operations = [ + migrations.CreateModel( + name='Reference', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('citation_count', models.IntegerField()), + ('authors', models.CharField(max_length=512)), + ('title', models.CharField(max_length=512)), + ('citation', models.CharField(max_length=512)), + ('vor', models.CharField(max_length=128)), + ('vor_url', models.URLField()), + ('publication', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='references', to='journals.Publication')), + ], + options={ + 'default_related_name': 'references', + 'ordering': ['-citation_count'], + }, + ), + migrations.AlterField( + model_name='doajdeposit', + name='timestamp', + field=models.CharField(max_length=40), + ), + migrations.AlterUniqueTogether( + name='reference', + unique_together=set([('citation_count', 'publication')]), + ), + ] diff --git a/journals/migrations/0004_auto_20180122_2109.py b/journals/migrations/0004_auto_20180122_2109.py new file mode 100644 index 0000000000000000000000000000000000000000..de58b2237846e33f49e27fca994656b72c05371a --- /dev/null +++ b/journals/migrations/0004_auto_20180122_2109.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-22 20:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('journals', '0003_auto_20180117_2323'), + ] + + operations = [ + migrations.AlterField( + model_name='publication', + name='accepted_submission', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='publication', to='submissions.Submission'), + ), + ] diff --git a/journals/migrations/0005_auto_20180122_1003.py b/journals/migrations/0005_auto_20180122_1003.py new file mode 100644 index 0000000000000000000000000000000000000000..86a398beb1bd80d31ef70f0ec9671df368326732 --- /dev/null +++ b/journals/migrations/0005_auto_20180122_1003.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-22 09:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('journals', '0004_auto_20180121_1202'), + ] + + operations = [ + migrations.AlterModelOptions( + name='reference', + options={'ordering': ['reference_number']}, + ), + migrations.RenameField( + model_name='reference', + old_name='citation_count', + new_name='reference_number', + ), + migrations.AlterField( + model_name='reference', + name='citation', + field=models.CharField(blank=True, max_length=512), + ), + migrations.AlterUniqueTogether( + name='reference', + unique_together=set([('reference_number', 'publication')]), + ), + ] diff --git a/journals/models.py b/journals/models.py index 9ffed4c252f4da7890dd28034a3bfd1e81831c33..c443f7f99d6392a1096dca531aa9b2d75069c4bb 100644 --- a/journals/models.py +++ b/journals/models.py @@ -51,6 +51,19 @@ class Journal(models.Model): def get_abbreviation_citation(self): return journal_name_abbrev_citation(self.name) + def citation_rate(self): + """ + Returns the citation rate in units of nr citations per article per year. + """ + pubs = Publication.objects.filter(in_issue__in_volume__in_journal=self) + ncites = 0 + deltat = 1 # to avoid division by zero + for pub in pubs: + if pub.citedby and pub.latest_citedby_update: + ncites += len(pub.citedby) + deltat += (pub.latest_citedby_update.date() - pub.publication_date).days + return (ncites * 365.25/deltat) + class Volume(models.Model): in_journal = models.ForeignKey('journals.Journal', on_delete=models.CASCADE) @@ -70,6 +83,19 @@ class Volume(models.Model): def doi_string(self): return '10.21468/' + self.doi_label + def citation_rate(self): + """ + Returns the citation rate in units of nr citations per article per year. + """ + pubs = Publication.objects.filter(in_issue__in_volume=self) + ncites = 0 + deltat = 1 # to avoid division by zero + for pub in pubs: + if pub.citedby and pub.latest_citedby_update: + ncites += len(pub.citedby) + deltat += (pub.latest_citedby_update.date() - pub.publication_date).days + return (ncites * 365.25/deltat) + class Issue(models.Model): in_volume = models.ForeignKey('journals.Volume', on_delete=models.CASCADE) @@ -121,6 +147,19 @@ class Issue(models.Model): return self.start_date <= timezone.now().date() and\ self.until_date >= timezone.now().date() + def citation_rate(self): + """ + Returns the citation rate in units of nr citations per article per year. + """ + pubs = Publication.objects.filter(in_issue=self) + ncites = 0 + deltat = 1 # to avoid division by zero + for pub in pubs: + if pub.citedby and pub.latest_citedby_update: + ncites += len(pub.citedby) + deltat += (pub.latest_citedby_update.date() - pub.publication_date).days + return (ncites * 365.25/deltat) + class Publication(models.Model): """ @@ -128,7 +167,8 @@ class Publication(models.Model): the actual publication file, author data, etc. etc. """ # Publication data - accepted_submission = models.OneToOneField('submissions.Submission', on_delete=models.CASCADE) + accepted_submission = models.OneToOneField('submissions.Submission', on_delete=models.CASCADE, + related_name='publication') in_issue = models.ForeignKey('journals.Issue', on_delete=models.CASCADE) paper_nr = models.PositiveSmallIntegerField() @@ -217,6 +257,40 @@ class Publication(models.Model): + ', ' + self.get_paper_nr() + ' (' + self.publication_date.strftime('%Y') + ')') + def citation_rate(self): + """ + Returns the citation rate in units of nr citations per article per year. + """ + if self.citedby and self.latest_citedby_update: + ncites = len(self.citedby) + deltat = (self.latest_citedby_update.date() - self.publication_date).days + return (ncites * 365.25/deltat) + else: + return 0 + + +class Reference(models.Model): + """ + A Refence is a reference used in a specific Publication. + """ + reference_number = models.IntegerField() + publication = models.ForeignKey('journals.Publication', on_delete=models.CASCADE) + + authors = models.CharField(max_length=512) + title = models.CharField(max_length=512) + citation = models.CharField(max_length=512, blank=True) + + vor = models.CharField(max_length=128) + vor_url = models.URLField() + + class Meta: + unique_together = ('reference_number', 'publication') + ordering = ['reference_number'] + default_related_name = 'references' + + def __str__(self): + return '[{}] {}'.format(self.reference_number, self.publication.doi_label) + class Deposit(models.Model): """ @@ -226,20 +300,22 @@ class Deposit(models.Model): All deposit history is thus contained here. """ publication = models.ForeignKey(Publication, on_delete=models.CASCADE) - timestamp = models.CharField(max_length=40, default='') - doi_batch_id = models.CharField(max_length=40, default='') - metadata_xml = models.TextField(blank=True, null=True) + timestamp = models.CharField(max_length=40) + doi_batch_id = models.CharField(max_length=40) + metadata_xml = models.TextField(blank=True) metadata_xml_file = models.FileField(blank=True, null=True, max_length=512) deposition_date = models.DateTimeField(blank=True, null=True) - response_text = models.TextField(blank=True, null=True) + response_text = models.TextField(blank=True) deposit_successful = models.NullBooleanField(default=None) class Meta: ordering = ['-timestamp'] def __str__(self): - return (self.deposition_date.strftime('%Y-%m-%D') + - ' for ' + self.publication.doi_label) + _str = '' + if self.deposition_date: + _str += '%s for ' % self.deposition_date.strftime('%Y-%m-%D') + return _str + self.publication.doi_label class DOAJDeposit(models.Model): @@ -247,7 +323,7 @@ class DOAJDeposit(models.Model): For the Directory of Open Access Journals. """ publication = models.ForeignKey(Publication, on_delete=models.CASCADE) - timestamp = models.CharField(max_length=40, default='') + timestamp = models.CharField(max_length=40) metadata_DOAJ = JSONField() metadata_DOAJ_file = models.FileField(blank=True, null=True, max_length=512) deposition_date = models.DateTimeField(blank=True, null=True) diff --git a/journals/templates/journals/manage_report_metadata.html b/journals/templates/journals/manage_report_metadata.html index cd2dce24d5ebcee24ff2c2c2860dec19c8319f3e..9d491ccecc3aa31612ba24beca5503d0e33114cf 100644 --- a/journals/templates/journals/manage_report_metadata.html +++ b/journals/templates/journals/manage_report_metadata.html @@ -21,13 +21,24 @@ event: "focusin" {% block content %} + <div class="rol"> + <div class="col-12"> + {% for page in reports.paginator.page_range %} + {% if forloop.counter != 1 %} | {% endif %} + <a href="?page={{ page }}">{{ page }}</a> + {% endfor %} + </div> + </div> + <table class="table table-hover mb-5"> <thead class="thead-default"> <tr> <th>Submission</th> + <th>Associated doi</th> <th>Report nr</th> - <th>Needs doi</th> + <th>Needs own doi</th> + <th>own doi</th> <th>Latest successful Crossref deposit</th> <th>Deposit needs updating?</th> </tr> @@ -37,13 +48,15 @@ event: "focusin" {% for report in reports %} <tr data-toggle="collapse" data-parent="#accordion" href="#collapse{{ report.id }}" aria-expanded="true" aria-controls="collapse{{ report.id }}" style="cursor: pointer;"> <td>{{ report.submission.arxiv_identifier_w_vn_nr }}</td> + <td>{{ report.associated_published_doi }}</td> <td>{{ report.report_nr }}</td> <td>{{ report.needs_doi }}</td> + <td>{{ report.doi_label }}</td> <td>{{ report|latest_successful_crossref_deposit_report }}</td> <td>{{ report.doideposit_needs_updating }}</td> </tr> <tr id="collapse{{ report.id }}" class="collapse" role="tabpanel" aria-labelledby="heading{{ report.id }}" style="background-color: #fff;"> - <td colspan="5"> + <td colspan="7"> <p><a href="{{ report.submission.get_absolute_url }}">{{ report.submission.arxiv_identifier_w_vn_nr }}</a>, <a href="{{ report.get_absolute_url }}">{{ report.report_nr }}</a></p> <h2 class="ml-3">Actions</h2> @@ -89,4 +102,15 @@ event: "focusin" </tbody> </table> + +<div class="rol"> + <div class="col-12"> + {% for page in reports.paginator.page_range %} + {% if forloop.counter != 1 %} | {% endif %} + <a href="?page={{ page }}">{{ page }}</a> + {% endfor %} + </div> +</div> + + {% endblock content %} diff --git a/journals/templates/journals/metadata_xml_deposit.html b/journals/templates/journals/metadata_xml_deposit.html index a6e405b3c01252b3b7b659446258325597ad1f30..0f40882d3e4f459ebd331fc81fcf12d3a708f4e8 100644 --- a/journals/templates/journals/metadata_xml_deposit.html +++ b/journals/templates/journals/metadata_xml_deposit.html @@ -28,6 +28,7 @@ <div class="row"> <div class="col-12"> + {% if errormessage %} <h2 class="text-danger">{{ errormessage }}</h2> {% endif %} @@ -38,7 +39,9 @@ </div> <h3 class="mt-3">Response text:</h3> - <p>{{ response_text|linebreaks }}</p> + <div> + <pre><code>{{ response_text|linebreaks }}</code></pre> + </div> <h3><a href="{{publication.get_absolute_url}}">return to the publication's page</a>, to the <a href="{% url 'journals:manage_metadata' %}">general metadata management page</a> or to <a href="{% url 'journals:manage_metadata' doi_label=publication.doi_label %}">this publication's metadata management page</a></h3> diff --git a/journals/templates/journals/publication_detail.html b/journals/templates/journals/publication_detail.html index a02fa03f8809361ed24f0dac7de156c36278cee4..67fbaf1ab5263eba5682c59cc0dcf7b7f3dcbcf0 100644 --- a/journals/templates/journals/publication_detail.html +++ b/journals/templates/journals/publication_detail.html @@ -7,6 +7,8 @@ {% block pagetitle %}: {{ publication.citation }} - {{ publication.title }}{% endblock pagetitle %} +{% block body_class %}{{ block.super }} publication{% endblock %} + {% block breadcrumb_items %} {{block.super}} <a href="{{journal.get_absolute_url}}" class="breadcrumb-item">{{journal}}</a> @@ -58,7 +60,6 @@ </p> {% endif %} - <hr> {% if publication.citedby|length >= 1 %} <div class="row"> @@ -79,21 +80,17 @@ <div class="row"> <div class="col-12"> - <h3>View more material from these authors:</h3> - <p> - {% for author in publication.authors.all %} - <a href="{{author.get_absolute_url}}">{{ author }}</a> {% if not forloop.last %} · {% endif %} - - {% if forloop.last %} - {% if publication.authors_unregistered.exists %} - · - {% endif %} - {% endif %} - {% endfor %} - {% for author in publication.authors_unregistered.all %} - {{ author }} {% if not forloop.last %} · {% endif %} - {% endfor %} - </p> + <h3>Authors</h3> + <ul> + {% for author in publication.authors.all %} + <li><a href="{{author.get_absolute_url}}">{{ author }}</a></li> + {% endfor %} + {% for author in publication.authors_unregistered.all %} + <li>{{ author }}</li> + {% endfor %} + </ul> + + {% include 'partials/journals/references.html' with publication=publication %} {% if is_edcol_admin %} {# This function is not available for public yet! #} @@ -165,6 +162,7 @@ <li><a href="{% url 'journals:harvest_citedby_links' publication.doi_label %}">Update Crossref cited-by links</a></li> <li><a href="{% url 'journals:manage_metadata' %}">Metadata management page</a></li> <li><a href="{% url 'journals:manage_metadata' doi_label=publication.doi_label %}">This publication's metadata management page</a></li> + <li><a href="{% url 'journals:update_references' doi_label=publication.doi_label %}">Update references</a></li> </ul> </div> </div> diff --git a/journals/templates/journals/sign_existing_report.html b/journals/templates/journals/sign_existing_report.html index 99b8db35f47f12abc642bc14ddad4f0b96eb5a78..422659cd787f3887bd2c3ca8d230a118a83a33f1 100644 --- a/journals/templates/journals/sign_existing_report.html +++ b/journals/templates/journals/sign_existing_report.html @@ -4,30 +4,46 @@ {% block pagetitle %}: sign existing Report{% endblock pagetitle %} +{% block breadcrumb %} +<div class="container-outside breadcrumb-nav"> + <div class="container"> + <nav class="breadcrumb"> + <a href="{% url 'submissions:submissions' %}" class="breadcrumb-item">Submissions</a> + <a href="{{ report.submission.get_absolute_url }}" class="breadcrumb-item">{{ report.submission.arxiv_identifier_w_vn_nr }}</a> + <span class="breadcrumb-item">Sign existing Report</span> + + </nav> + </div> +</div> +{% endblock %} + {% block content %} <div class="row"> - <div class="col-12"> - <hr class="hr12"> - <div class="row"> - <div class="col-6"> - <h2>Confirmation page: do you wish to sign this Report?</h2> - <h3>(your Report is reproduced below for your convenience)</h3> - </div> - <div class="col-6"> - <form action="{% url 'journals:sign_existing_report' report_id=report.id %}" method="post"> - {% csrf_token %} - {{ form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Submit" /> - </form> - </div> + <div class="col-12"> + <h1 class="highlight">Sign existing Report</h1> </div> +</div> - <h3>Report on Submission <a href="{{report.submission.get_absolute_url}}">{{report.submission.title}}</a></h3> - - {% include 'submissions/_single_public_report_without_comments.html' with report=report user=request.user perms=perms %} +<div class="row"> + <div class="col-md-6"> + <h2>Confirmation page: do you wish to sign this Report?</h2> + <h3>(your Report is reproduced below for your convenience)</h3> + </div> + <div class="col-md-6"> + <form action="{% url 'journals:sign_existing_report' report_id=report.id %}" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-secondary" type="submit" value="Submit" /> + </form> + </div> +</div> - </div> +<div class="row"> + <div class="col-12"> + <h3>Report on Submission <a href="{{report.submission.get_absolute_url}}">{{report.submission.title}}</a></h3> + {% include 'submissions/_single_public_report_without_comments.html' with report=report user=request.user perms=perms %} + </div> </div> {% endblock %} diff --git a/journals/templates/journals/update_references.html b/journals/templates/journals/update_references.html new file mode 100644 index 0000000000000000000000000000000000000000..9d490a4cd1f65184a80d0444f2289ac784daf386 --- /dev/null +++ b/journals/templates/journals/update_references.html @@ -0,0 +1,50 @@ +{% extends 'scipost/base.html' %} + +{% load bootstrap %} + +{% block pagetitle %}: Update References{% endblock pagetitle %} + +{% block breadcrumb %} + <div class="container-outside header"> + <div class="container"> + <nav class="breadcrumb hidden-sm-down"> + <a href="{{publication.get_absolute_url}}" class="breadcrumb-item">{{publication.citation}}</a> + <span class="breadcrumb-item active">Update References</span> + </nav> + </div> + </div> +{% endblock %} + +{% block content %} + +<h1>Update References</h1> + +<form action="{% url 'journals:update_references' publication.doi_label %}" method="get" class="mb-4"> + + <div class="form-group row"> + <label class="col-form-label col-md-4 text-right" for="id_email">Number of additional empty references</label> + <div class="col-md-8"> + <input class="form-control" name="extra" type="number" value="{{ request.GET.extra|default:'0' }}"> + </div> + </div> + <div class="ml-auto col-md-8 multiple-checkbox"> + <label for="prefiller_checkbox"> + <input type="checkbox" name="prefill" value="form" id="prefiller_checkbox"> + Prefill form with Crossref data (this might take a minute) + </label> + </div> + <input type="submit" class="btn btn-primary" value="Refresh"> +</form> + +<hr> + +<form action="{% url 'journals:update_references' publication.doi_label %}" method="post" enctype="multipart/form-data"> + {% csrf_token %} + {{ formset|bootstrap }} + <input type="submit" class="btn btn-primary" value="Submit"> +</form> + + + + +{% endblock %} diff --git a/journals/templates/partials/journals/references.html b/journals/templates/partials/journals/references.html new file mode 100644 index 0000000000000000000000000000000000000000..6467b62ea35106c4f7295bb502a4ac5954e4adac --- /dev/null +++ b/journals/templates/partials/journals/references.html @@ -0,0 +1,14 @@ +{% if publication.references.all %} + <h3>References ({{ publication.references.all|length }})</h3> + <a class="mb-2 d-block" href="javascript:;" data-toggle="toggle" data-target="#reference_list">Click to expand</a> + <ul class="references" id="reference_list" style="display:none;"> + {% for reference in publication.references.all %} + <li> + <span class="counter">[{{ reference.reference_number }}]</span> + <span class="authors">{{ reference.authors }}</span>, + <span class="title">{{ reference.title }}</span>{% if reference.citation %}, <span class="citation">{{ reference.citation|safe }}</span>{% endif %} + <span class="doi">doi: <a href="{{ reference.vor_url }}" target="_blank">{{ reference.vor }}</a></span> + </li> + {% endfor %} + </ul> +{% endif %} diff --git a/journals/urls/general.py b/journals/urls/general.py index 5570b662718dd4458c5d43ddd33f02efb8df178d..fe28da6578e252e6d3521331a7673122159998ba 100644 --- a/journals/urls/general.py +++ b/journals/urls/general.py @@ -53,6 +53,8 @@ urlpatterns = [ url(r'^create_citation_list_metadata/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', journals_views.create_citation_list_metadata, name='create_citation_list_metadata'), + url(r'^update_references/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', + journals_views.update_references, name='update_references'), url(r'^create_funding_info_metadata/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', journals_views.create_funding_info_metadata, name='create_funding_info_metadata'), diff --git a/journals/views.py b/journals/views.py index ae5562dfd3e6e727cb706c789c15da175f215b32..06edc2905c7199c411b8dce3f7207e9d0adf349d 100644 --- a/journals/views.py +++ b/journals/views.py @@ -3,27 +3,29 @@ import json import os import random import requests +import shutil import string import xml.etree.ElementTree as ET + from django.contrib.auth.decorators import login_required from django.contrib.contenttypes.models import ContentType +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.urlresolvers import reverse -from django.core.files.base import ContentFile from django.conf import settings from django.contrib import messages -from django.http import Http404 +from django.db import transaction +from django.http import Http404, HttpResponse from django.utils import timezone from django.shortcuts import get_object_or_404, render, redirect -from django.db import transaction -from django.http import HttpResponse from .exceptions import PaperNumberingError from .helpers import paper_nr_string, issue_doi_label_from_doi_label from .models import Journal, Issue, Publication, UnregisteredAuthor, Deposit, DOAJDeposit,\ GenericDOIDeposit from .forms import FundingInfoForm, InitiatePublicationForm, ValidatePublicationForm,\ - UnregisteredAuthorForm, CreateMetadataXMLForm, CitationListBibitemsForm + UnregisteredAuthorForm, CreateMetadataXMLForm, CitationListBibitemsForm,\ + ReferenceFormSet from .utils import JournalUtils from comments.models import Comment @@ -447,6 +449,32 @@ def create_citation_list_metadata(request, doi_label): return render(request, 'journals/create_citation_list_metadata.html', context) +@permission_required('scipost.can_publish_accepted_submission', return_403=True) +def update_references(request, doi_label): + """ + Update the References for a certain Publication. + """ + publication = get_object_or_404(Publication, doi_label=doi_label) + references = publication.references.all() + + formset = ReferenceFormSet(request.POST or None, queryset=references, publication=publication, + extra=request.GET.get('extra')) + + if request.GET.get('prefill'): + formset.prefill() + + if formset.is_valid(): + formset.save() + messages.success(request, 'References saved') + return redirect(publication.get_absolute_url()) + + context = { + 'publication': publication, + 'formset': formset, + } + return render(request, 'journals/update_references.html', context) + + @permission_required('scipost.can_publish_accepted_submission', return_403=True) @transaction.atomic def create_funding_info_metadata(request, doi_label): @@ -552,7 +580,7 @@ def create_metadata_xml(request, doi_label): '<timestamp>' + timezone.now().strftime('%Y%m%d%H%M%S') + '</timestamp>\n' '<depositor>\n' '<depositor_name>scipost</depositor_name>\n' - '<email_address>admin@scipost.org</email_address>\n' + '<email_address>' + settings.CROSSREF_DEPOSIT_EMAIL + '</email_address>\n' '</depositor>\n' '<registrant>scipost</registrant>\n' '</head>\n' @@ -719,6 +747,11 @@ def metadata_xml_deposit(request, doi_label, option='test'): Makes use of the python requests module. """ publication = get_object_or_404(Publication, doi_label=doi_label) + + if publication.metadata_xml is None: + errormessage = 'This publication has no metadata. Produce it first before saving it.' + return render(request, 'scipost/error.html', context={'errormessage': errormessage}) + timestamp = (publication.metadata_xml.partition( '<timestamp>'))[2].partition('</timestamp>')[0] doi_batch_id = (publication.metadata_xml.partition( @@ -726,46 +759,58 @@ def metadata_xml_deposit(request, doi_label, option='test'): path = (settings.MEDIA_ROOT + publication.in_issue.path + '/' + publication.get_paper_nr() + '/' + publication.doi_label.replace('.', '_') + '_Crossref_' + timestamp + '.xml') + if os.path.isfile(path): errormessage = 'The metadata file for this metadata timestamp already exists' return render(request, 'scipost/error.html', context={'errormessage': errormessage}) + if option == 'deposit' and not settings.DEBUG: # CAUTION: Real deposit only on production (non-debug-mode) url = 'http://doi.crossref.org/servlet/deposit' else: url = 'http://test.crossref.org/servlet/deposit' - if publication.metadata_xml is None: - errormessage = 'This publication has no metadata. Produce it first before saving it.' - return render(request, 'scipost/error.html', context={'errormessage': errormessage}) # First perform the actual deposit to Crossref params = { 'operation': 'doMDUpload', 'login_id': settings.CROSSREF_LOGIN_ID, 'login_passwd': settings.CROSSREF_LOGIN_PASSWORD, } - files = {'fname': ('metadata.xml', publication.metadata_xml, 'multipart/form-data')} + files = { + 'fname': ('metadata.xml', publication.metadata_xml.encode('utf-8'), 'multipart/form-data') + } r = requests.post(url, params=params, files=files) response_headers = r.headers response_text = r.text # Then create the associated Deposit object (saving the metadata to a file) if option == 'deposit': - content = ContentFile(publication.metadata_xml) deposit = Deposit(publication=publication, timestamp=timestamp, doi_batch_id=doi_batch_id, metadata_xml=publication.metadata_xml, deposition_date=timezone.now()) - deposit.metadata_xml_file.save(path, content) deposit.response_text = r.text + + # Save the filename with timestamp + path_with_timestamp = '{issue}/{paper}/{doi}_Crossref_{timestamp}.xml'.format( + issue=publication.in_issue.path, + paper=publication.get_paper_nr(), + doi=publication.doi_label.replace('.', '_'), + timestamp=timestamp) + f = open(settings.MEDIA_ROOT + path_with_timestamp, 'w', encoding='utf-8') + f.write(publication.metadata_xml) + f.close() + + # Copy file + path_without_timestamp = '{issue}/{paper}/{doi}_Crossref.xml'.format( + issue=publication.in_issue.path, + paper=publication.get_paper_nr(), + doi=publication.doi_label.replace('.', '_')) + shutil.copyfile(settings.MEDIA_ROOT + path_with_timestamp, + settings.MEDIA_ROOT + path_without_timestamp) + + deposit.metadata_xml_file = path_with_timestamp deposit.save() publication.latest_crossref_deposit = timezone.now() publication.save() - # Save a copy to the filename without timestamp - path1 = (settings.MEDIA_ROOT + publication.in_issue.path + '/' - + publication.get_paper_nr() + '/' + publication.doi_label.replace('.', '_') - + '_Crossref.xml') - f = open(path1, 'w') - f.write(publication.metadata_xml) - f.close() context = { 'option': option, @@ -807,6 +852,7 @@ def metadata_DOAJ_deposit(request, doi_label): Makes use of the python requests module. """ publication = get_object_or_404(Publication, doi_label=doi_label) + if not publication.metadata_DOAJ: messages.warning(request, '<h3>%s</h3>Failed: please first produce ' 'DOAJ metadata before depositing.' % publication.doi_label) @@ -820,8 +866,8 @@ def metadata_DOAJ_deposit(request, doi_label): if os.path.isfile(path): errormessage = 'The metadata file for this metadata timestamp already exists' return render(request, 'scipost/error.html', context={'errormessage': errormessage}) - url = 'https://doaj.org/api/v1/articles' + url = 'https://doaj.org/api/v1/articles' params = { 'api_key': settings.DOAJ_API_KEY, } @@ -833,21 +879,32 @@ def metadata_DOAJ_deposit(request, doi_label): publication.doi_label, r.text)) # Then create the associated Deposit object (saving the metadata to a file) - content = ContentFile(json.dumps(publication.metadata_DOAJ)) deposit = DOAJDeposit(publication=publication, timestamp=timestamp, metadata_DOAJ=publication.metadata_DOAJ, deposition_date=timezone.now()) - deposit.metadata_DOAJ_file.save(path, content) deposit.response_text = r.text - deposit.save() - # Save a copy to the filename without timestamp - path1 = (settings.MEDIA_ROOT + publication.in_issue.path + '/' - + publication.get_paper_nr() + '/' + publication.doi_label.replace('.', '_') - + '_DOAJ.json') - f = open(path1, 'w') + # Save a copy to the filename with and without timestamp + path_with_timestamp = '{issue}/{paper}/{doi}_DOAJ_{timestamp}.json'.format( + issue=publication.in_issue.path, + paper=publication.get_paper_nr(), + doi=publication.doi_label.replace('.', '_'), + timestamp=timestamp) + f = open(settings.MEDIA_ROOT + path_with_timestamp, 'w') f.write(json.dumps(publication.metadata_DOAJ)) f.close() + # Copy file + path_without_timestamp = '{issue}/{paper}/{doi}_DOAJ.json'.format( + issue=publication.in_issue.path, + paper=publication.get_paper_nr(), + doi=publication.doi_label.replace('.', '_')) + shutil.copyfile(settings.MEDIA_ROOT + path_with_timestamp, + settings.MEDIA_ROOT + path_without_timestamp) + + # Save the database entry + deposit.metadata_DOAJ_file = path_with_timestamp + deposit.save() + messages.success(request, '<h3>%s</h3>Successfull deposit of metadata DOAJ.' % publication.doi_label) return redirect(reverse('journals:manage_metadata', @@ -863,7 +920,7 @@ def mark_doaj_deposit_success(request, deposit_id, success): deposit.deposit_successful = False deposit.save() return redirect(reverse('journals:manage_metadata', - kwargs={'doi_label': deposit.publication.doi_label})) + kwargs={'doi_label': deposit.publication.doi_label})) @permission_required('scipost.can_publish_accepted_submission', return_403=True) @@ -893,7 +950,7 @@ def harvest_citedby_links(request, doi_label): 'xsi:schemaLocation="http://www.crossref.org/qschema/2.0 ' 'http://www.crossref.org/qschema/crossref_query_input2.0.xsd">' '<head>' - '<email_address>admin@scipost.org</email_address>' + '<email_address>' + settings.CROSSREF_DEPOSIT_EMAIL + '</email_address>' '<doi_batch_id>' + str(doi_batch_id) + '</doi_batch_id>' '</head>' '<body>' @@ -1001,6 +1058,16 @@ def manage_report_metadata(request): the metadata of Reports. """ reports = Report.objects.all() + paginator = Paginator(reports, 25) + + page = request.GET.get('page') + try: + reports = paginator.page(page) + except PageNotAnInteger: + reports = paginator.page(1) + except EmptyPage: + reports = paginator.page(paginator.num_pages) + context = { 'reports': reports, } @@ -1049,14 +1116,20 @@ def generic_metadata_xml_deposit(request, **kwargs): This method creates the metadata for non-Publication objects such as Reports and Comments, and deposits the metadata to Crossref. + If there exists a relation to a SciPost-published object, + the deposit uses Crossref's peer review content type. + Otherwise the deposit is done as a dataset. """ type_of_object = kwargs['type_of_object'] object_id = int(kwargs['object_id']) + if type_of_object == 'report': _object = get_object_or_404(Report, id=object_id) elif type_of_object == 'comment': _object = get_object_or_404(Comment, id=object_id) + relation_to_published = _object.relation_to_published + if not _object.doi_label: _object.create_doi_label() @@ -1067,37 +1140,86 @@ def generic_metadata_xml_deposit(request, **kwargs): salt = salt.encode('utf8') idsalt = str(_object)[:10] idsalt = idsalt.encode('utf8') - timestamp=timezone.now().strftime('%Y%m%d%H%M%S') + timestamp = timezone.now().strftime('%Y%m%d%H%M%S') doi_batch_id = hashlib.sha1(salt+idsalt).hexdigest() metadata_xml = ( '<?xml version="1.0" encoding="UTF-8"?>\n' - '<doi_batch version="4.4.0" xmlns="http://www.crossref.org/schema/4.4.0" ' + '<doi_batch version="4.4.1" xmlns="http://www.crossref.org/schema/4.4.1" ' 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' - 'xmlns:fr="http://www.crossref.org/fundref.xsd" ' - 'xsi:schemaLocation="http://www.crossref.org/schema/4.4.0 ' - 'http://www.crossref.org/shema/deposit/crossref4.4.0.xsd" ' - 'xmlns:ai="http://www.crossref.org/AccessIndicators.xsd">\n' + 'xsi:schemaLocation="http://www.crossref.org/schema/4.4.1 ' + 'http://www.crossref.org/shema/deposit/crossref4.4.1.xsd">\n' '<head>\n' '<doi_batch_id>' + str(doi_batch_id) + '</doi_batch_id>\n' '<timestamp>' + timestamp + '</timestamp>\n' '<depositor>\n' '<depositor_name>scipost</depositor_name>\n' - '<email_address>admin@scipost.org</email_address>\n' + '<email_address>' + settings.CROSSREF_DEPOSIT_EMAIL + '</email_address>\n' '</depositor>\n' '<registrant>scipost</registrant>\n' '</head>\n' - '<body>\n' - '<database>\n' - '<database_metadata language="en">\n' - '<titles><title>SciPost Reports and Comments</title></titles>\n' - '</database_metadata>\n' - '<dataset dataset_type="collection">\n' - '<doi_data><doi>' + _object.doi_string + '</doi>\n' - '<resource>https://scipost.org' + _object.get_absolute_url() + '</resource></doi_data>\n' - '</dataset></database>\n' - '</body></doi_batch>' + ) + if relation_to_published: + metadata_xml += ( + '<body>\n' + '<peer_review stage="' + relation_to_published['stage'] + '">\n' + '<contributors>' ) - if not settings.DEBUG: + if _object.anonymous: + metadata_xml += ( + '<anonymous sequence="first" contributor_role="' + + relation_to_published['contributor_role'] + '"/>' + ) + else: + metadata_xml += ( + '<person_name sequence="first" contributor_role="' + + relation_to_published['contributor_role'] + '">' + '<given_name>' + _object.author.user.first_name + '</given_name>' + '<surname>' + _object.author.user.last_name + '</surname>' + '</person_name>\n' + ) + + if isinstance(_object, Publication): + url_to_declare = 'https://scipost.org{}'.format(_object.get_absolute_url()) + else: + url_to_declare = 'https://scipost.org/{}'.format(_object.doi_label) + + metadata_xml += ( + '</contributors>\n' + '<titles><title>' + relation_to_published['title'] + '</title></titles>\n' + '<review_date>' + '<month>' + _object.date_submitted.strftime('%m') + '</month>' + '<day>' + _object.date_submitted.strftime('%d') + '</day>' + '<year>' + _object.date_submitted.strftime('%Y') + '</year>' + '</review_date>\n' + '<program xmlns="http://www.crossref.org/relations.xsd">\n' + '<related_item>' + '<description>' + relation_to_published['title'] + '</description>\n' + '<inter_work_relation relationship-type="isReviewOf" identifier-type="doi">' + + relation_to_published['isReviewOfDOI'] + '</inter_work_relation></related_item>\n' + '</program>' + '<doi_data><doi>' + _object.doi_string + '</doi>\n' + '<resource>' + url_to_declare + + '</resource></doi_data>\n' + '</peer_review>\n' + '</body>\n' + '</doi_batch>\n' + ) + else: + metadata_xml += ( + '<body>\n' + '<database>\n' + '<database_metadata language="en">\n' + '<titles><title>SciPost Reports and Comments</title></titles>\n' + '</database_metadata>\n' + '<dataset dataset_type="collection">\n' + '<doi_data><doi>' + _object.doi_string + '</doi>\n' + '<resource>https://scipost.org' + _object.get_absolute_url() + + '</resource></doi_data>\n' + '</dataset></database>\n' + '</body></doi_batch>' + ) + + if not settings.CROSSREF_DEBUG: # CAUTION: Debug is False, production goes for real deposit!!! url = 'http://doi.crossref.org/servlet/deposit' else: @@ -1145,6 +1267,21 @@ def mark_generic_deposit_success(request, deposit_id, success): # Viewing # ########### +def report_detail(request, doi_label): + report = get_object_or_404(Report.objects.accepted(), doi_label=doi_label) + return redirect(report.get_absolute_url()) + + +def comment_detail(request, doi_label): + comment = get_object_or_404(Comment.objects.vetted().regular_comments(), doi_label=doi_label) + return redirect(comment.get_absolute_url()) + + +def author_reply_detail(request, doi_label): + comment = get_object_or_404(Comment.objects.vetted().author_replies(), doi_label=doi_label) + return redirect(comment.get_absolute_url()) + + def publication_detail(request, doi_label): publication = Publication.objects.get_published(doi_label=doi_label) journal = publication.in_issue.in_volume.in_journal diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py index 35c279649c84fc40da52a185334e9ecacea13701..36a786563117ac25975e17bc3520a63a35a04084 100644 --- a/scipost/management/commands/add_groups_and_permissions.py +++ b/scipost/management/commands/add_groups_and_permissions.py @@ -198,6 +198,12 @@ class Command(BaseCommand): name='Can manage Reports', content_type=content_type) + # Statistics + can_view_statistics, created = Permission.objects.get_or_create( + codename='can_view_statistics', + name='Can view statistics', + content_type=content_type) + # Voting can_prepare_recommendations_for_voting, created = Permission.objects.get_or_create( codename='can_prepare_recommendations_for_voting', @@ -300,6 +306,7 @@ class Command(BaseCommand): can_view_all_production_streams, can_promote_to_production_team, can_manage_affiliations, + can_view_statistics, ]) FinancialAdmin.permissions.set([ @@ -310,6 +317,7 @@ class Command(BaseCommand): can_manage_registration_invitations, change_draft_invitation, can_attend_VGMs, + can_view_statistics, ]) EditorialAdmin.permissions.set([ @@ -332,12 +340,14 @@ class Command(BaseCommand): can_take_decisions_related_to_proofs, can_upload_proofs, can_run_proofs_by_authors, + can_view_statistics, ]) EditorialCollege.permissions.set([ can_view_pool, can_take_charge_of_submissions, can_attend_VGMs, + can_view_statistics, ]) VettingEditors.permissions.set([ diff --git a/scipost/managers.py b/scipost/managers.py index b62ac59bb7cfdf7faa5990ed6afa2f20b55e812b..b16b82034b11303f60ffa2074a90b55b3a51b86a 100644 --- a/scipost/managers.py +++ b/scipost/managers.py @@ -52,6 +52,9 @@ class UnavailabilityPeriodManager(models.Manager): def today(self): return self.filter(start__lte=today, end__gte=today) + def future(self): + return self.filter(end__gte=today) + class AuthorshipClaimQuerySet(models.QuerySet): def awaiting_vetting(self): diff --git a/scipost/services.py b/scipost/services.py index 3df2ce70fb903edf7ea290f81830ce69094d566c..908f731778c2fed20ab70b253a88a3819e6d2acc 100644 --- a/scipost/services.py +++ b/scipost/services.py @@ -3,11 +3,17 @@ import feedparser import requests import datetime import dateutil.parser +import logging + +arxiv_logger = logging.getLogger('scipost.services.arxiv') +doi_logger = logging.getLogger('scipost.services.doi') class DOICaller: def __init__(self, doi_string): self.doi_string = doi_string + doi_logger.info('New DOI call for %s' % doi_string) + self._call_crosslink() if self.is_valid: self._format_data() @@ -15,18 +21,37 @@ class DOICaller: def _call_crosslink(self): url = 'http://api.crossref.org/works/%s' % self.doi_string request = requests.get(url) + + doi_logger.info('GET [{doi}] [request] | {url}'.format( + doi=self.doi_string, + url=url, + )) + if request.ok: self.is_valid = True self._crossref_data = request.json()['message'] else: self.is_valid = False + doi_logger.info('GET [{doi}] [response {valid}] | {response}'.format( + doi=self.doi_string, + valid='VALID' if self.is_valid else 'INVALID', + response=request.text, + )) + def _format_data(self): data = self._crossref_data title = data['title'][0] - author_list = ['{} {}'.format(author['given'], author['family']) for author in data['author']] - # author_list is given as a comma separated list of names on the relevant models (Commentary, Submission) - author_list = ", ".join(author_list) + + # author_list is given as a comma separated list of names on the relevant models + author_list = [] + for author in data['author']: + try: + author_list.append('{} {}'.format(author['given'], author['family'])) + except KeyError: + author_list.append(author['name']) + author_list = ', '.join(author_list) + journal = data['container-title'][0] volume = data.get('volume', '') pages = self._get_pages(data) @@ -41,6 +66,11 @@ class DOICaller: 'pub_date': pub_date, } + doi_logger.info('GET [{doi}] [formatted data] | {data}'.format( + doi=self.doi_string, + data=self.data, + )) + def _get_pages(self, data): # For Physical Review pages = data.get('article-number', '') @@ -54,8 +84,8 @@ class DOICaller: if date_parts: date_parts = date_parts[0] year = date_parts[0] - month = date_parts[1] - day = date_parts[2] + month = date_parts[1] if len(date_parts) > 1 else 1 + day = date_parts[2] if len(date_parts) > 2 else 1 pub_date = datetime.date(year, month, day).isoformat() else: pub_date = '' @@ -68,6 +98,7 @@ class ArxivCaller: def __init__(self, identifier): self.identifier = identifier + arxiv_logger.info('New ArXiv call for identifier %s' % identifier) self._call_arxiv() if self.is_valid: self._format_data() @@ -76,14 +107,25 @@ class ArxivCaller: url = self.query_base_url % self.identifier request = requests.get(url) response_content = feedparser.parse(request.content) - arxiv_data = response_content['entries'][0] - if self._search_result_present(arxiv_data): + arxiv_logger.info('GET [{arxiv}] [request] | {url}'.format( + arxiv=self.identifier, + url=url, + )) + + if self._search_result_present(response_content): + arxiv_data = response_content['entries'][0] self.is_valid = True self._arxiv_data = arxiv_data self.metadata = response_content else: self.is_valid = False + arxiv_logger.info('GET [{arxiv}] [response {valid}] | {response}'.format( + arxiv=self.identifier, + valid='VALID' if self.is_valid else 'INVALID', + response=response_content, + )) + def _format_data(self): data = self._arxiv_data title = data['title'] @@ -102,6 +144,12 @@ class ArxivCaller: 'abstract': abstract, # Duplicate for Commentary/Submission cross-compatibility 'pub_date': pub_date, } + arxiv_logger.info('GET [{arxiv}] [formatted data] | {data}'.format( + arxiv=self.identifier, + data=self.data, + )) def _search_result_present(self, data): - return 'title' in data + if len(data.get('entries', [])) > 0: + return 'title' in data['entries'][0] + return False diff --git a/scipost/static/scipost/SciPost.css b/scipost/static/scipost/SciPost.css index 59a65ec9ace010ea561c03571b2d1dc1cf80645e..44e1b4c27a9f5f124ba0bfed164a4ffca84c4685 100644 --- a/scipost/static/scipost/SciPost.css +++ b/scipost/static/scipost/SciPost.css @@ -486,32 +486,6 @@ table.tablePadded10 td { background-color: #990000; } -.reportRatings { - font-family: 'Merriweather Sans'; - font-size: 11px; - margin: 0 4px; - padding: 0; - display: inline-block; - box-shadow: 0 1px 0 1px #ccc; - background: #f4f4f4; -} -.reportRatings ul { - display: inline-block; - font-family: 'Merriweather Sans'; - margin: 0; - padding: 2px 1px; -} -.reportRatings ul li { - border: 1px solid #002b49; - display: inline-block; - font-family: 'Merriweather Sans'; - margin: 0 3px; - padding: 4px 7px; - border-radius: 1px; - background-color: #f1f1f1; -} - - article { background-color:#eeeeee; border: 1px solid grey; border-radius:5px; diff --git a/scipost/static/scipost/assets/config/preconfig.scss b/scipost/static/scipost/assets/config/preconfig.scss index c6a977bfc80f6313bf2b4b00941ba3a0ad0f4b30..a9b5266ee232496003ad1e192a0c62ba668a0b79 100644 --- a/scipost/static/scipost/assets/config/preconfig.scss +++ b/scipost/static/scipost/assets/config/preconfig.scss @@ -17,13 +17,6 @@ $alert-padding-x: 0.75rem; // Grid // $grid-gutter-width: 20px; -// $container-max-widths: ( -// xs: , -// sm: 728px, -// md: 720px, -// lg: 960px, -// xl: 1140px -// ); // Colors // @@ -66,7 +59,6 @@ $alert-border-radius: $base-border-radius; // Cards // $card-border-radius: $base-border-radius; -$card-bg: $gray-200; $card-border-color: $gray-200; $card-spacer-x: 0.75rem; $card-spacer-y: 0.5rem; diff --git a/scipost/static/scipost/assets/css/_form.scss b/scipost/static/scipost/assets/css/_form.scss index 9c191958d781f582c61e74e78362e292a377fe9b..e0182d0420dcb8d74eccf2521dc7e72103560f7e 100644 --- a/scipost/static/scipost/assets/css/_form.scss +++ b/scipost/static/scipost/assets/css/_form.scss @@ -110,3 +110,10 @@ input[type="file"] { } } } + +// Overwrite this weird Bootstrap css rule +select.form-control { + &:not([size]):not([multiple]) { + height: auto; + } +} diff --git a/scipost/static/scipost/assets/css/_journals.scss b/scipost/static/scipost/assets/css/_journals.scss index a2f1946f4558a8964fab6ceb18be41f0224f4d4a..490351d34a4027661c60611b65fa9f5d33d07893 100644 --- a/scipost/static/scipost/assets/css/_journals.scss +++ b/scipost/static/scipost/assets/css/_journals.scss @@ -74,3 +74,10 @@ ul.publicationClickables { } } } + + +.publication { + .abstract { + margin-bottom: 0; + } +} diff --git a/scipost/static/scipost/assets/css/_list_group.scss b/scipost/static/scipost/assets/css/_list_group.scss index 4755ec289813f41a3be705df5c68db980d203c26..6bf5d2d7e491a3d7bcfea4be366bfaa8f00d9884 100644 --- a/scipost/static/scipost/assets/css/_list_group.scss +++ b/scipost/static/scipost/assets/css/_list_group.scss @@ -23,3 +23,25 @@ ul.events-list { } } } + + +.fa-li { + line-height: 1.25 !important; +} + +ul.references { + list-style: none; + padding-left: 0; + + .counter { + margin-right: 0.25rem; + } + + .title { + font-style: italic; + } + .doi { + display: block; + margin: 0 0 0.2rem 1.5rem; + } +} diff --git a/scipost/static/scipost/assets/css/_nav.scss b/scipost/static/scipost/assets/css/_nav.scss index 974bcde176520b2f82900249c0c8a030a514c39e..d33cb87ddac8b2f23a73f83970814fe8d1764fca 100644 --- a/scipost/static/scipost/assets/css/_nav.scss +++ b/scipost/static/scipost/assets/css/_nav.scss @@ -71,3 +71,8 @@ nav.main-nav { .nav { flex-wrap: nowrap; } + +.tab-pane .loading { + text-align: center; + padding: 3rem; +} diff --git a/scipost/static/scipost/assets/css/_navbar.scss b/scipost/static/scipost/assets/css/_navbar.scss index c74f30a0f50d61d9ff505251fbcd1dfa3548353d..8b32a2115a3afdcae2c6d4f521dbdf295a5c026e 100644 --- a/scipost/static/scipost/assets/css/_navbar.scss +++ b/scipost/static/scipost/assets/css/_navbar.scss @@ -15,10 +15,10 @@ .navbar-nav { flex-direction: row; - overflow: scroll; - -ms-overflow-style: none; + overflow: auto; + // -ms-overflow-style: none; -webkit-overflow-scrolling: touch; - overflow: -moz-scrollbars-none; + // overflow: -moz-scrollbars-none; .nav-link { padding-left: .5rem; @@ -29,17 +29,17 @@ } // Hide scrollbars... trying to -::-webkit-scrollbar, -::-webkit-scrollbar-button, -::-webkit-scrollbar-track, -::-webkit-scrollbar-track-piece, -::-webkit-scrollbar-thumb, -::-webkit-scrollbar-corner, -::-webkit-resizer { - display: none; - background: rgba(0,0,0,0); - background-color: rgba(0,0,0,0); -} +// ::-webkit-scrollbar, +// ::-webkit-scrollbar-button, +// ::-webkit-scrollbar-track, +// ::-webkit-scrollbar-track-piece, +// ::-webkit-scrollbar-thumb, +// ::-webkit-scrollbar-corner, +// ::-webkit-resizer { +// // display: none; +// background: rgba(0,0,0,0); +// background-color: rgba(0,0,0,0); +// } .container-outside { &.main-nav { diff --git a/scipost/static/scipost/assets/css/_reports.scss b/scipost/static/scipost/assets/css/_reports.scss new file mode 100644 index 0000000000000000000000000000000000000000..871bb5accdaf88fc863fe537b54214286203a04a --- /dev/null +++ b/scipost/static/scipost/assets/css/_reports.scss @@ -0,0 +1,42 @@ +.report { + ul.clickables { + display: inline-block; + list-style: none; + margin: 0.5rem 0 0 0; + padding: 0; + + li { + padding: 0 0 0.25rem 0; + } + + .citation { + font-style: italic; + } + } + + .comment { + margin-top: 1rem; + } +} + + +.ratings { + background-color: #f4f4f4; + display: inline-block; + border: 1px solid #ddd; + text-transform: capitalize; + + > ul { + list-style: none; + display: flex; + padding: 0; + margin: 0; + + li { + border: 1px solid #ddd; + margin: 2px 2px; + padding: 0.25rem 0.5rem; + background: $body-bg; + } + } +} diff --git a/scipost/static/scipost/assets/css/_submissions.scss b/scipost/static/scipost/assets/css/_submissions.scss index 3dae5291ec7064cdbdbe6ec349c416222af1106b..f41deda48852a0f3e890647e5527955234e42e60 100644 --- a/scipost/static/scipost/assets/css/_submissions.scss +++ b/scipost/static/scipost/assets/css/_submissions.scss @@ -17,7 +17,7 @@ table.submission_header { box-shadow: 0 1px 0 0 $card-shadow-color; border: 1px solid; border-color: $card-grey-border-color; - z-index: -1; + z-index: 1; border-radius: $border-radius 0 $border-radius $border-radius; } @@ -37,34 +37,6 @@ table.submission_header { } } -.reportRatings { - font-size: 10px; - margin: 0.5rem 0 1rem; - padding: 0.3rem 0.5rem 0.4rem; - display: inline-block; - box-shadow: 0 1px 0 0 #ccc; - background: #f9f9f9; - border: 1px solid; - border-color: #ececec #ececec #d0d1d5; - border-radius: 2px; - - ul { - margin: 0; - padding: 0; - - li { - border: 1px solid; - display: inline-block; - margin: 0.1rem; - padding: 0.25rem 0.5rem; - border-color: #e5e6e9 #dfe0e4 #d0d1d5; - border-radius: 2px; - background: #fff; - box-shadow: 0 1px 0 0 #ccc; - } - } -} - .required-actions { padding: 0.5rem; background-color: $red; diff --git a/scipost/static/scipost/assets/css/_type.scss b/scipost/static/scipost/assets/css/_type.scss index 52798b0cc849833716e0725dcdda5b0687be69a6..f6eef699ad9eada0e0f37bebe7f9b58259e326c0 100644 --- a/scipost/static/scipost/assets/css/_type.scss +++ b/scipost/static/scipost/assets/css/_type.scss @@ -67,10 +67,9 @@ h5 { } .highlight { - background-color: #f4f4f4; + background-color: $body-bg; border-radius: $card-border-radius; - border: 1px solid #ececec; - box-shadow: 0 1px 0 0 $card-shadow-color; + border: 1px solid #ddd; &.tight { display: inline-block; @@ -119,6 +118,18 @@ hr.hr12 { &.small { height: 1px; } + + &.divider { + height: 10px; + border-radius: 0; + background-color: $body-bg; + margin-left: -$grid-gutter-width; + margin-right: -$grid-gutter-width; + margin-top: 1.5rem; + margin-bottom: 1.5rem; + box-shadow: none; + width: auto; + } } .text-blue { diff --git a/scipost/static/scipost/assets/css/scipost-physics.scss b/scipost/static/scipost/assets/css/scipost-physics.scss index 816d3a46be9e8b8e21cd44e3bc375fee10233b2b..381822f4dfd9e0796319f1ec57093e9eb95c18a5 100644 --- a/scipost/static/scipost/assets/css/scipost-physics.scss +++ b/scipost/static/scipost/assets/css/scipost-physics.scss @@ -32,7 +32,7 @@ &.active { color: #002b49; background: rgba(255, 255, 255, 0.5); - box-shadow: 0 1px 0 0 #ccc; + box-shadow: 0 1px 0 0 #ddd; } } } diff --git a/scipost/static/scipost/assets/css/style.scss b/scipost/static/scipost/assets/css/style.scss index ddd9fc91b2ca14722ee634cfe12ee1f75cb090a8..6e6fca92a968ba2d2d382a858ba4c5e410042741 100644 --- a/scipost/static/scipost/assets/css/style.scss +++ b/scipost/static/scipost/assets/css/style.scss @@ -48,6 +48,7 @@ @import "icons"; @import "journals"; @import "personal_page"; +@import "reports"; @import "submissions"; diff --git a/scipost/static/scipost/assets/js/dynamic_loading.js b/scipost/static/scipost/assets/js/dynamic_loading.js new file mode 100644 index 0000000000000000000000000000000000000000..5064be98fb68d318671d523bd3694ce75d0efb3c --- /dev/null +++ b/scipost/static/scipost/assets/js/dynamic_loading.js @@ -0,0 +1,54 @@ +function dynamic_load_tab( target_tab ) { + var tab = $(target_tab); + var url = tab.attr('sp-dynamic-load'); + if(tab.data('sp-loaded') == 'true') { + // window.history.replaceState('scipost', document.title, url); + return; // Only load once + } + + var target = $(tab.attr('href')); + $(target) + .show() + .html('<div class="loading"><i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i></div>'); + + $.get(url).done(function(data) { + $(target).html(data).promise().done(function() { + tab.data('sp-loaded', 'true'); + }); + + // window.history.replaceState('scipost', document.title, url); + }); +} + +$(function(){ + // Change `tab` GET parameter for page-reload + $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + dynamic_load_tab( e.target ) + }) + $('[data-toggle="tab"][sp-autoload="true"]').tab('show'); + + // Simple simple Angular-like loading! + $('a[data-toggle="dynamic"]').on('click', function(event) { + event.preventDefault(); + var self = this, + url = $(this).attr('href'), + target = $(this).attr('data-target'); + + $(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) { + $(target).html(data).promise().done(function() { + init_page(); + }); + $('[data-target="active-list"]') + .find('> li') + .removeClass('active') + $(self).parents('[data-target="active-list"] > li') + .addClass('active'); + + window.history.replaceState('scipost', document.title, url); + }); + }); +}); diff --git a/scipost/static/scipost/assets/js/scripts.js b/scipost/static/scipost/assets/js/scripts.js index 62d164fb742284d5822e5663d37e7cab1e401187..4e96974ec3df7596e5d8cdc9f2fbafa8daedad99 100644 --- a/scipost/static/scipost/assets/js/scripts.js +++ b/scipost/static/scipost/assets/js/scripts.js @@ -59,12 +59,6 @@ $(function(){ // Remove all alerts in screen automatically after 15sec. setTimeout(function() {hide_all_alerts()}, 15000); - // Change `tab` GET parameter for page-reload - $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { - var tab_name = e.target.hash.substring(1) - window.history.replaceState({}, null, '?tab=' + tab_name); - }); - init_page(); // Simple simple Angular-like loading! diff --git a/scipost/templates/partials/scipost/personal_page/account.html b/scipost/templates/partials/scipost/personal_page/account.html new file mode 100644 index 0000000000000000000000000000000000000000..bcb731d9b2bb8a84ff3b75b0403485f9c52db829 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/account.html @@ -0,0 +1,184 @@ +{% load bootstrap %} +{% load user_groups %} + +{# 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"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title mb-0">Your Account</h2> + </div> + </div> + </div> +</div> +<div class="row"> + <div class="col-md-6"> + <h3>Your personal details:</h3> + {% include "scipost/_private_info_as_table.html" with contributor=contributor %} + + {% if contributor %} + {# Scientist fields #} + <h3 class="mt-3">Your main discipline:</h3> + <ul><li>{{ contributor.get_discipline_display }}</li></ul> + + <h3 class="mt-3">Your expertises:</h3> + {% if contributor.expertises %} + {% include "scipost/_expertises_as_ul.html" with contributor=contributor %} + {% else %} + <p>You haven't listed your expertise(s).<br/> + Do so by <a href="{% url 'scipost:update_personal_data' %}">updating your personal data</a> + </p> + {% endif %} + {# END: Scientist fields #} + {% endif %} + </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 #} + {% endif %} + + {% if not contributor.petition_signatories.exists %} + <div class="border border-danger p-2"> + <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 %} + + {% if is_scipost_admin %} + <h3>You are a SciPost Administrator.</h3> + {% endif %} + {% if is_edcol_admin %} + <h3>You are a SciPost Editorial Administrator.</h3> + {% endif %} + {% if is_advisory_board %} + <h3>You are a member of the Advisory Board.</h3> + {% endif %} + {% if is_editorial_college %} + <h3>You are a member of the Editorial College.</h3> + {% endif %} + {% if is_vetting_editor %} + <h3>You are a SciPost Vetting Editor.</h3> + {% endif %} + {% if is_registered_contributor %} + <h3>You are a Registered Contributor.</h3> + {% endif %} + {% if is_tester %} + <h3>You are a SciPost Tester.</h3> + {% endif %} + {% if is_ambassador %} + <h3>You are a SciPost Ambassador.</h3> + {% endif %} + {% if is_junior_ambassador %} + <h3>You are a SciPost Junior Ambassador.</h3> + {% endif %} + {% 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> + <li><a href="{% url 'scipost:update_personal_data' %}">Update your personal data</a></li> + <li><a href="{% url 'scipost:change_password' %}">Change your password</a></li> + </ul> + </div> +</div> + +{% if unavailability_form %} + <hr> + <div class="row"> + <div class="col"> + <h2 class="highlight">Your Availability</h2> + </div> + </div> + <div class="row justify-content-center"> + <div class="col-md-4 mr-md-5"> + <p>To help with the editorial workflow, you can inform us of any periods during which you are unavailable. We will do our best to respect these.</p> + <h3 class="mb-3">Mark a period as unavailable:</h3> + <form action="{% url 'scipost:mark_unavailable_period' %}" method="post"> + {% csrf_token %} + {{ unavailability_form|bootstrap }} + <input class="btn btn-secondary" type="submit" value="Submit" /> + </form> + </div> + <div class="col-md-4 ml-md-5"> + {% if unavailabilities %} + <h3>Your unavailability periods in our records</h3> + <p class="text-muted">(YYYY-MM-DD)</p> + <table class="table"> + <tr> + <th>Start</th> + <th colspan="2">End</th> + </tr> + {% for unav in unavailabilities %} + <tr> + <td>{{ unav.start }}</td> + <td>{{ unav.end }}</td> + <td> + <form action="{% url 'scipost:delete_unavailable_period' unav.id %}" method="post"> + {% csrf_token %} + <input class="btn btn-danger" type="submit" value="Delete" /> + </form> + </td> + </tr> + {% endfor %} + </table> + {% else %} + <p>You don't have any upcoming unavailability periods on record.</p> + {% endif %} + </div> + </div> +{% endif %} diff --git a/scipost/templates/partials/scipost/personal_page/author_replies.html b/scipost/templates/partials/scipost/personal_page/author_replies.html new file mode 100644 index 0000000000000000000000000000000000000000..2149474b1344a93ed81533cd57b93ce41af54ce0 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/author_replies.html @@ -0,0 +1,23 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title mb-0">Your Author Replies</h2> + </div> + </div> + </div> +</div> + +<div class="row" id="myauthorreplieslist"> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for own_reply in own_authorreplies %} + <li class="list-group-item"> + {% include 'comments/_comment_card_extended_for_author.html' with comment=own_reply %} + </li> + {% empty %} + <li class="list-group-item"><em>You do not have Author Replies yet.</em></li> + {% endfor %} + </ul> + </div> +</div> diff --git a/scipost/templates/partials/scipost/personal_page/commentaries.html b/scipost/templates/partials/scipost/personal_page/commentaries.html new file mode 100644 index 0000000000000000000000000000000000000000..2e50be5535ef30f630b23b89d014ade1d59e8e30 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/commentaries.html @@ -0,0 +1,32 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Commentaries</h2> + <ul class="mb-0"> + {% if nr_commentary_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_commentary_authorships_to_claim}})</a></li> + {% endif %} + <li><a href="{% url 'commentaries:request_commentary' %}">Request opening a SciPost Commentary Page</a></li> + </ul> + </div> + </div> + </div> +</div> + +<div class="row" id="mycommentarieslist"> + <div class="col-12"> + <h3>Commentaries for which you are identified as an author:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for com in own_commentaries %} + <li class="list-group-item"> + {% include 'commentaries/_commentary_card_content.html' with commentary=com %} + </li> + {% empty %} + <li class="list-group-item"><em>No Commentaries found</em></li> + {% endfor %} + </ul> + </div> +</div> diff --git a/scipost/templates/partials/scipost/personal_page/comments.html b/scipost/templates/partials/scipost/personal_page/comments.html new file mode 100644 index 0000000000000000000000000000000000000000..f6a5f52db29c21f347f7cc59073eb7ed99940173 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/comments.html @@ -0,0 +1,23 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title mb-0">Your Comments</h2> + </div> + </div> + </div> +</div> + +<div class="row" id="mycommentslist"> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for own_comment in own_comments %} + <li class="list-group-item"> + {% include 'comments/_comment_card_extended_for_author.html' with comment=own_comment %} + </li> + {% empty %} + <li class="list-group-item"><em>You have not commented yet.</em></li> + {% endfor %} + </ul> + </div> +</div> diff --git a/scipost/templates/partials/scipost/personal_page/editorial_actions.html b/scipost/templates/partials/scipost/personal_page/editorial_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..ffd9844f50aeebf31bc1b66010cab5049542eb23 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/editorial_actions.html @@ -0,0 +1,167 @@ + +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title mb-0">Pending Editorial Actions</h2> + </div> + </div> + </div> +</div> + +<div class="row"> + {% if perms.scipost.can_vet_registration_requests or perms.scipost.can_draft_registration_invitations or perms.scipost.can_manage_registration_invitations %} + <div class="col-md-4"> + <h3>Registration actions</h3> + <ul> + {% if perms.scipost.can_vet_registration_requests %} + <li><a href="{% url 'scipost:vet_registration_requests' %}">Vet Registration requests</a> ({{ nr_reg_to_vet }})</li> + {% endif %} + {% if perms.scipost.can_resend_registration_requests %} + <li><a href="{% url 'scipost:registration_requests' %}">Awaiting validation</a> ({{ nr_reg_awaiting_validation }})</li> + {% endif %} + {% if perms.scipost.can_draft_registration_invitations %} + <li><a href="{% url 'scipost:draft_registration_invitation' %}">Draft a Registration Invitation</a></li> + {% endif %} + {% if perms.scipost.can_manage_registration_invitations %} + <li><a href="{% url 'scipost:registration_invitations' %}">Manage Registration Invitations</a></li> + {% endif %} + </ul> + + {% if perms.scipost.can_manage_registration_invitations %} + <h3>Notifications</h3> + <ul> + <li><a href="{% url 'scipost:citation_notifications' %}">Manage citation notifications</a></li> + </ul> + {% endif %} + + {% if is_scipost_admin %} + <h3>Email communications</h3> + <ul> + {% if perms.scipost.can_email_group_members %} + <li><a href="{% url 'scipost:email_group_members' %}">Email Group Members</a></li> + {% endif %} + {% if perms.scipost.can_email_particulars %} + <li><a href="{% url 'scipost:send_precooked_email' %}">Send a precooked email</a></li> + <li><a href="{% url 'scipost:email_particular' %}">Email a particular individual/address</a></li> + {% endif %} + {% if perms.scipost.can_manage_mailchimp %} + <li><a href="{% url 'mailing_lists:overview' %}">Manage mailing lists</a></li> + {% endif %} + </ul> + + <h3>SciPost Administation</h3> + <ul> + <li><a href="{% url 'affiliations:institutions' %}">Manage Institutions database</a></li> + </ul> + {% endif %} + + {% if perms.scipost.can_view_timesheets %} + <h3>Finance</h3> + <ul> + <li><a href="{% url 'finances:timesheets' %}">Production Team Timesheets</a></li> + </ul> + {% endif %} + </div> + {% endif %} + + <div class="col-md-4"> + {% if perms.scipost.can_vet_comments or perms.scipost.can_vet_submitted_reports %} + <h3>Vetting actions</h3> + <ul> + {% if perms.scipost.can_vet_commentary_requests %} + <li><a href="{% url 'commentaries:vet_commentary_requests' %}">Vet Commentary Page requests</a> ({{ nr_commentary_page_requests_to_vet }})</li> + {% endif %} + {% if perms.scipost.can_vet_comments %} + <li><a href="{% url 'comments:vet_submitted_comments_list' %}">Vet submitted Comments</a> ({{ nr_comments_to_vet }})</li> + {% endif %} + {% if perms.scipost.can_vet_thesislink_requests %} + <li><a href="{% url 'theses:unvetted_thesislinks' %}">Vet Thesis Link Requests</a> ({{ nr_thesislink_requests_to_vet }})</li> + {% endif %} + {% if perms.scipost.can_vet_authorship_claims %} + <li><a href="{% url 'scipost:vet_authorship_claims' %}">Vet Authorship Claims</a> ({{ nr_authorship_claims_to_vet }})</li> + {% endif %} + {% if perms.scipost.can_vet_submitted_reports %} + <li><a href="{% url 'submissions:vet_submitted_reports_list' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> + {% endif %} + </ul> + {% endif %} + + {% if perms.scipost.can_oversee_refereeing %} + <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> + <li><a href="{% url 'submissions:pool' %}">Submissions Pool</a></li> + <li><a href="{% url 'submissions:treated_submissions_list' %}">Fully treated Submissions</a>{% if nr_treated_submissions_without_pdf %} ({{nr_treated_submissions_without_pdf}} unfinished){% endif %}</li> + <li><a href="{% url 'journals:harvest_citedby_list' %}">Harvest citedby data</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 '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 'proceedings:proceedings' %}">Manage Proceedings Issues</a></li> + </ul> + {% endif %} + + {% if perms.scipost.can_attend_VGMs %} + <h3>Virtual General Meetings</h3> + <ul> + <li><a href="{% url 'virtualmeetings:VGMs' %}">List of VGMs</a></li> + </ul> + {% endif %} + </div> + + {% if perms.scipost.can_oversee_refereeing or perms.scipost.can_take_charge_of_submissions %} + <div class="col-md-4"> + <h3>Info</h3> + <ul> + <li><a href="{% url 'submissions:editorial_workflow' %}">How-to guide: summary of the editorial workflow</a></li> + </ul> + + <h3>Submissions assignments</h3> + <ul> + <li><a href="{% url 'submissions:assignments' %}">Your assignments</a></li> + <li><a href="{% url 'scipost:Fellow_activity_overview' %}">View assignments overview</a></li> + + {% if perms.scipost.can_assign_submissions %} + <li>Assign Submissions via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_submissions_to_assign }})</li> + {% endif %} + {% if perms.scipost.can_take_charge_of_submissions %} + <li>Accept or decline assignments via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_assignments_to_consider }})</li> + {% endif %} + </ul> + + {% if perms.scipost.can_oversee_refereeing %} + <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 %} +</div> + +{% if active_assignments %} + <div class="row"> + <div class="col-12"> + <h3 class="highlight">Submissions for which you are Editor-in-charge</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for assignment in active_assignments %} + <li class="list-group-item"> + <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> + </div> + </div> +{% endif %} diff --git a/scipost/templates/partials/scipost/personal_page/publications.html b/scipost/templates/partials/scipost/personal_page/publications.html new file mode 100644 index 0000000000000000000000000000000000000000..302090e22d865ec6c41654a8311462e886883fb5 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/publications.html @@ -0,0 +1,36 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Publications</h2> + <ul class="mb-0"> + {% if nr_publication_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_publication_authorships_to_claim}})</a></li> + {% endif %} + </ul> + </div> + </div> + </div> +</div> + + +<div class="row" id="mypublicationslist"> + <div class="col-12"> + <h3 class="mb-3">Publications for which you are identified as an author:</h3> + </div> + <div class="col-12"> + <ul class="list-unstyled"> + {% for pub in own_publications %} + <li> + <div class="card card-grey card-publication" id="{{pub.doi_label}}"> + {% include 'journals/_publication_card_content.html' with publication=pub current_user=request.user %} + </div> + </li> + {% empty %} + <li> + <em>No Publications found</em> + </li> + {% endfor %} + </ul> + </div> +</div> diff --git a/scipost/templates/partials/scipost/personal_page/refereeing.html b/scipost/templates/partials/scipost/personal_page/refereeing.html new file mode 100644 index 0000000000000000000000000000000000000000..877189bf00c38496e2f037c5dc6a6cedfa90484b --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/refereeing.html @@ -0,0 +1,88 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Refereeing Tasks</h2> + <ul class="mb-0"> + <li><a href="{% url 'submissions:accept_or_decline_ref_invitations' %}">Accept/decline refereeing invitations</a> ({{ contributor.referee_invitations.open.count }})</li> + </ul> + </div> + </div> + </div> +</div> + +<div class="row"> + <div class="col-12"> + <h3>Pending Refereeing Tasks:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for task in contributor.referee_invitations.in_process.all %} + <li class="list-group-item"> + <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> + {% endfor %} + </ul> + </div> +</div> + +{% if contributor.reports.in_draft.all %} + <div class="row"> + <div class="col-12"> + <h3>Unfinished reports:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for report in contributor.reports.in_draft.all %} + <li class="list-group-item"> + <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> + </div> + </div> +{% endif %} + +{% if contributor.reports.non_draft.all %} + <div class="row"> + <div class="col-12"> + <h3>Finished reports:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for report in contributor.reports.non_draft.all %} + <li class="list-group-item"> + {% 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 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> + <th style='min-width: 100px;'>Received:</th><td>{{ report.date_submitted|date:'Y-n-j' }}<td> + </tr> + <tr> + <th>Status:</th><td {% if report.status == 'vetted' %}class="text-success"{% elif report.status == 'unvetted' %}class="text-danger"{% endif %}>{{report.get_status_display}}</td> + </tr> + {% if report.doi_label %} + <tr> + <th>DOI:</th><td>{{ report.doi_string }}</td></th> +{% endif %} + <tr> + <th>Anonymous:</th><td>{{report.anonymous|yesno:'Yes,No'}}</td>{% if report.anonymous %}<td>You can <a href="{% url 'journals:sign_existing_report' report_id=report.id %}">click here to sign this Report</a> (leads to confirmation page){% endif %}</td> + </tr> + </table> + </div> + </li> + {% endfor %} + </ul> + </div> + </div> +{% endif %} diff --git a/scipost/templates/partials/scipost/personal_page/submissions.html b/scipost/templates/partials/scipost/personal_page/submissions.html new file mode 100644 index 0000000000000000000000000000000000000000..10215feea9d957c33393ba981509d81b0b40779f --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/submissions.html @@ -0,0 +1,50 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Submissions</h2> + <ul class="mb-0"> + {% if nr_submission_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_submission_authorships_to_claim }})</a></li> + {% endif %} + <li><a href="{% url 'submissions:submit_manuscript' %}">Submit an arXiv preprint to a SciPost Journal</a></li> + </ul> + </div> + </div> + </div> +</div> + +{# {% if own_submissions %}#} +<div class="row" id="mysubmissionslist"> + <div class="col-12"> + <h3>Submissions for which you are identified as an author:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for sub in own_submissions %}nr_submission_authorships_to_claim, + <li class="list-group-item"> + <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"> + <em>No Submissions found</em> + </li> + {% endfor %} + </ul> + </div> +</div> +{# {% endif %}#} diff --git a/scipost/templates/partials/scipost/personal_page/theses.html b/scipost/templates/partials/scipost/personal_page/theses.html new file mode 100644 index 0000000000000000000000000000000000000000..de0e22998d920a70b8a3ac95e133ae82c0d9c372 --- /dev/null +++ b/scipost/templates/partials/scipost/personal_page/theses.html @@ -0,0 +1,32 @@ +<div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Theses</h2> + <ul class="mb-0"> + {% if nr_thesis_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_thesis_authorships_to_claim}})</a></li> + {% endif %} + <li><a href="{% url 'theses:request_thesislink' %}">Request a SciPost ThesisLink</a></li> + </ul> + </div> + </div> + </div> +</div> + +<div class="row" id="mytheseslist"> + <div class="col-12"> + <h3>Theses for which you are identified as an author:</h3> + </div> + <div class="col-12"> + <ul class="list-group list-group-flush"> + {% for thesis in own_thesislinks %} + <li class="list-group-item"> + {% include 'theses/_thesislink_card_content.html' with thesislink=thesis %} + </li> + {% empty %} + <li class="list-group-item"><em>No Theses found</em></li> + {% endfor %} + </ul> + </div> +</div> diff --git a/scipost/templates/scipost/about.html b/scipost/templates/scipost/about.html index e247402657e12b3d3191c89bbad4c34cd80a742c..81a6d25c9a8d329ee16a6025a7b8ef591d0af2c3 100644 --- a/scipost/templates/scipost/about.html +++ b/scipost/templates/scipost/about.html @@ -3,35 +3,28 @@ {% block pagetitle %}: About{% endblock pagetitle %} {% load staticfiles %} - {% load scipost_extras %} -{% block content %} +{% block breadcrumb %} + <div class="container-outside header"> + <div class="container"> + <h1>About SciPost</h1> + </div> + </div> +{% endblock %} -<div class="row"> - <div class="col-md-6"> - <h2 class="highlight">About SciPost</h2> +{% block content %} +<div class="row"> + <div class="col"> <p>SciPost is a complete scientific publication portal.</p> <p>It is purely online-based, and offers freely, openly, globally and perpetually accessible science.</p> <p>Being managed by professional scientists, and making use of editor-solicited and contributed reviews, its Journals aim at the highest achievable standards of refereeing.</p> <p>SciPost Commentaries allow Contributors to seamlessly comment on all existing literature.</p> <h4><a href="{% url 'scipost:FAQ' %}">Frequently asked questions</a></h4> </div> - <div class="col-md-6"> - <h2 class="highlight">Acknowledgements</h2> - - <h2>SciPost is endorsed by</h2> - - <div class="row"> - <div class="col-12"> - <a target="_blank" href="http://www.nwo.nl/en"><img src="{% static 'scipost/images/NWO_logo_EN.jpg' %}" alt="NWO logo" width='300px' /></a> - <p id="NWOOpenAccess" class="mt-3">All articles published in SciPost Journals fulfill the Gold standard Open Access requirements of the NWO, as stipulated on the NWO’s <a href="http://www.nwo.nl/en/policies/open+science">Open Science page</a>.</p> - </div> - </div> - </div> </div> <hr> @@ -82,7 +75,7 @@ <h3>Code Development and Server Maintenance</h3> <ul> <li>J.-S. Caux</li> - <li>J. de Wit</li> + <li>J. de Wit</li> </ul> <p><em>with special thanks to M. Moeys, B. Ponsioen and G. Kapteijns</em></p> </div> @@ -92,16 +85,16 @@ <div class="col-md-4 col-lg-3"> <h3>Editorial Admin</h3> <ul> - <li>M. Vonk</li> + <li>A. de Hoogh</li> </ul> </div> <div class="col-md-7 col-lg-6"> <h3>Production</h3> <ul> <li>T. Zwart</li> + <li>T. Bouma</li> + <li>L. Ligthart</li> <li>P. Verhagen</li> - <li>S. Sánchez López</li> - <li>T. Ritmeester</li> </ul> </div> </div> @@ -116,24 +109,24 @@ <div class="row justify-content-center"> <div class="col-lg-3 col-md-4"> <ul> - <li>Prof. <a target="_blank" href="http://www.nikhef.nl/~h02/">J. J. Engelen</a><br/>(U. van Amsterdam)</li> - <li>Prof. <a target="_blank" href="https://www.asc.ox.ac.uk/person/18">P. Fendley</a><br/>(Oxford; <a href="https://www.asc.ox.ac.uk/all-souls-college-oxford">All Souls College</a>)</li> - <li>Prof. <a target="_blank" href="http://www.ru.nl/highenergyphysics/ehep/persons/sijbrand_de_jong/">S. J. de Jong</a><br/>(Radboud Univ. Nijmegen,<br/>President CERN Council)</li> + <li>Prof. <a target="_blank" href="//www.nikhef.nl/~h02/">J. J. Engelen</a><br/>(U. van Amsterdam)</li> + <li>Prof. <a target="_blank" href="//www.asc.ox.ac.uk/person/18">P. Fendley</a><br/>(Oxford; <a href="https://www.asc.ox.ac.uk/all-souls-college-oxford">All Souls College</a>)</li> + <li>Prof. <a target="_blank" href="//www.ru.nl/highenergyphysics/ehep/persons/sijbrand_de_jong/">S. J. de Jong</a><br/>(Radboud Univ. Nijmegen,<br/>President CERN Council)</li> </ul> </div> <div class="col-lg-3 col-md-4"> <ul> - <li>Prof. <a target="_blank" href="http://www.ens-lyon.fr/PHYSIQUE/presentation/annuaire/maillet-jean-michel">J. M. Maillet</a><br/>(ENS Lyon)</li> - <li>Prof. <a target="_blank" href="http://www.ru.nl/ssi/members/theo_rasing/">T. Rasing</a><br/>(Radboud Univ. Nijmegen)</li> - <li>Prof. <a target="_blank" href="http://atomchip.org/general-information/people/schmiedmayer/">J. Schmiedmayer</a><br/>(TU Vienna)</li> + <li>Prof. <a target="_blank" href="//www.ens-lyon.fr/PHYSIQUE/presentation/annuaire/maillet-jean-michel">J. M. Maillet</a><br/>(ENS Lyon)</li> + <li>Prof. <a target="_blank" href="//www.ru.nl/ssi/members/theo_rasing/">T. Rasing</a><br/>(Radboud Univ. Nijmegen)</li> + <li>Prof. <a target="_blank" href="//atomchip.org/general-information/people/schmiedmayer/">J. Schmiedmayer</a><br/>(TU Vienna)</li> </ul> </div> <div class="col-lg-3 col-md-4"> <ul> - <li>Prof. <a target="_blank" href="http://www.professoren.tum.de/en/spohn-herbert/">H. Spohn</a><br/>(TU Munich)</li> - <li>Prof. <a target="_blank" href="http://www.comp.phys.ethz.ch/people/troyer.html">M. Troyer</a><br/>(ETH Zurich)</li> - <li>Prof. <a target="_blank" href="http://www.uva.nl/over-de-uva/organisatie/medewerkers/content/v/e/e.p.verlinde/e.p.verlinde.html">E. P. Verlinde</a><br/>(U. van Amsterdam)</li> - <li>Prof. <a target="_blank" href="https://staff.fnwi.uva.nl/j.t.m.walraven/walraven/JookWalraven.htm">J. T. M. Walraven</a><br/>(U. van Amsterdam)</li> + <li>Prof. <a target="_blank" href="//www.professoren.tum.de/en/spohn-herbert/">H. Spohn</a><br/>(TU Munich)</li> + <li>Prof. <a target="_blank" href="//www.comp.phys.ethz.ch/people/troyer.html">M. Troyer</a><br/>(ETH Zurich)</li> + <li>Prof. <a target="_blank" href="//www.uva.nl/over-de-uva/organisatie/medewerkers/content/v/e/e.p.verlinde/e.p.verlinde.html">E. P. Verlinde</a><br/>(U. van Amsterdam)</li> + <li>Prof. <a target="_blank" href="//staff.fnwi.uva.nl/j.t.m.walraven/walraven/JookWalraven.htm">J. T. M. Walraven</a><br/>(U. van Amsterdam)</li> </ul> </div> </div> diff --git a/scipost/templates/scipost/comments_block.html b/scipost/templates/scipost/comments_block.html index bc60d0b67be828c920578e4ae16aa2194351bb3c..d3fa22a5a38ba0bf1a51739ff35d9ebc1250258e 100644 --- a/scipost/templates/scipost/comments_block.html +++ b/scipost/templates/scipost/comments_block.html @@ -1,19 +1,19 @@ {% if comments %} -<hr> -<div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Comments{% if type_of_object %} on this {{type_of_object}}{% endif %}</h2> - <a href="javascript:;" data-toggle="toggle" data-target="#commentslist">Toggle comments view</a> + + <div class="row"> + <div class="col-12"> + <div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title mb-0">Comments{% if type_of_object %} on this {{type_of_object}}{% endif %}</h2> + <a href="javascript:;" data-toggle="toggle" data-target="#commentslist">Toggle comments view</a> + </div> </div> </div> </div> -</div> -<div id="commentslist"> - {% for comment in comments %} - {% include 'comments/_single_comment_with_link.html' with comment=comment perms=perms user=request.user %} - {% endfor %} -</div> + <div id="commentslist"> + {% for comment in comments %} + {% include 'comments/_single_comment_with_link.html' with comment=comment perms=perms user=request.user %} + {% endfor %} + </div> {% endif %} diff --git a/scipost/templates/scipost/foundation.html b/scipost/templates/scipost/foundation.html index 8b5691c24416a1bee3ae432c73a30f49a9b1b565..75430efccb88624bb861a053398ca155faa504e5 100644 --- a/scipost/templates/scipost/foundation.html +++ b/scipost/templates/scipost/foundation.html @@ -43,7 +43,7 @@ <div class="row"> <div class="col-12"> <div class="card-deck"> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">SciPost Board</h2> <ul> @@ -55,7 +55,7 @@ </div> </div> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Contact details</h2> <address class="px-2"> @@ -71,16 +71,14 @@ </div> </div> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Registration</h2> - <div class="px-2"> - <p> - Dutch Chamber of Commerce nr 65280083.</br> - RSIN 856049487.<br> - <a href="{% static 'scipost/info/uittreksel_Stichting_SciPost.pdf' %}">Registration extract</a>. - </p> - </div> + <p class="px-2"> + Dutch Chamber of Commerce nr 65280083.</br> + RSIN 856049487.<br> + <a href="{% static 'scipost/info/uittreksel_Stichting_SciPost.pdf' %}">Registration extract</a>. + </p> </div> </div> </div> @@ -90,20 +88,20 @@ <div class="row"> <div class="col-12"> <div class="card-deck"> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Registration</h2> </div> </div> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Yearly Reports</h2> <p class="px-2">2016 (to be published)</p> </div> </div> - <div class="card border-0"> + <div class="card bg-white border-0"> <div class="card-body"> <h2 class="highlight">Financial Reports</h2> <p class="px-2">2016-7 (to be published)</p> diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index 68989e3ceeae91a9ccc3ac05ce413e13399f17e4..07ef2154191f647be2d7e03d1addc02b35542ea6 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -45,40 +45,40 @@ <!-- Nav tabs --> <ul class="nav btn-group personal-page-nav" role="tablist"> <li class="nav-item btn btn-secondary"> - <a href="#account" class="nav-link active" data-toggle="tab">Account</a> + <a class="nav-link" {% if tab == 'account' %}sp-autoload='true'{% endif %} href="#account" sp-dynamic-load="{% url 'scipost:personal_page_account' %}" data-toggle="tab">Account</a> </li> {% 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> + <a class="nav-link" {% if tab == 'editorial_actions' %}sp-autoload='true'{% endif %} href="#editorial-actions" sp-dynamic-load="{% url 'scipost:personal_page_editorial_actions' %}" data-toggle="tab">Editorial Actions</a> </li> {% endif %} {% if perms.scipost.can_referee %} <li class="nav-item btn btn-secondary"> - <a class="nav-link" data-toggle="tab" href="#refereeing">Refereeing {% if refereeing_tab_total_count %}({{refereeing_tab_total_count}}){% endif %}</a> + <a class="nav-link" {% if tab == 'refereeing' %}sp-autoload='true'{% endif %} data-toggle="tab" href="#refereeing" sp-dynamic-load="{% url 'scipost:personal_page_refereeing' %}">Refereeing {% if refereeing_tab_total_count %}({{refereeing_tab_total_count}}){% endif %}</a> </li> {% endif %} {% if contributor %} {# If user is contributor #} <li class="nav-item btn btn-secondary"> - <a class="nav-link" data-toggle="tab" href="#publications">Publications</a> + <a class="nav-link" {% if tab == 'publications' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_publications' %}" href="#publications">Publications</a> </li> <li class="nav-item btn btn-secondary"> - <a class="nav-link" data-toggle="tab" href="#submissions">Submissions</a> + <a class="nav-link" {% if tab == 'submissions' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_submissions' %}" href="#submissions">Submissions</a> </li> <li class="nav-item btn btn-secondary"> - <a class="nav-link" data-toggle="tab" href="#commentaries">Commentaries</a> + <a class="nav-link" {% if tab == 'commentaries' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_commentaries' %}" href="#commentaries">Commentaries</a> </li> <li class="nav-item btn btn-secondary"> - <a class="nav-link" data-toggle="tab" href="#theses">Theses</a> + <a class="nav-link" {% if tab == 'theses' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_theses' %}" href="#theses">Theses</a> </li> <li class="nav-item btn btn-secondary"> {% with contributor.comments.regular_comments.awaiting_vetting.count as count %} - <a class="nav-link" data-toggle="tab" href="#comments">Comments{% if count %} ({{count}} unvetted){% endif %}</a> + <a class="nav-link" {% if tab == 'comments' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_comments' %}" href="#comments">Comments{% if count %} ({{count}} unvetted){% endif %}</a> {% endwith %} </li> <li class="nav-item btn btn-secondary"> {% with contributor.comments.author_replies.awaiting_vetting.count as count %} - <a class="nav-link" data-toggle="tab" href="#author-replies">Author Replies{% if count %} ({{count}} unvetted){% endif %}</a> + <a class="nav-link" {% if tab == 'author_replies' %}sp-autoload='true'{% endif %} data-toggle="tab" sp-dynamic-load="{% url 'scipost:personal_page_author_replies' %}" href="#author-replies">Author Replies{% if count %} ({{count}} unvetted){% endif %}</a> {% endwith %} </li> {# END: If user is contributor #} @@ -92,667 +92,45 @@ <div class="tab-content"> <!-- Tab: Account --> <div class="tab-pane active" id="account" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Your Account</h2> - </div> - </div> - </div> - </div> - <div class="row"> - <div class="col-md-6"> - <h3>Your personal details:</h3> - {% include "scipost/_private_info_as_table.html" with contributor=contributor %} - - {% if contributor %} - {# Scientist fields #} - <h3 class="mt-3">Your main discipline:</h3> - <ul><li>{{ contributor.get_discipline_display }}</li></ul> - - <h3 class="mt-3">Your expertises:</h3> - {% if contributor.expertises %} - {% include "scipost/_expertises_as_ul.html" with contributor=contributor %} - {% else %} - <p>You haven't listed your expertise(s).<br/> - Do so by <a href="{% url 'scipost:update_personal_data' %}">updating your personal data</a> - </p> - {% endif %} - {# END: Scientist fields #} - {% endif %} - </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 #} - {% endif %} - - {% if not request.user.contributor.petition_signatories.exists %} - <div class="border border-danger p-2"> - <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 %} - - {% if is_scipost_admin %} - <h3>You are a SciPost Administrator.</h3> - {% endif %} - {% if is_edcol_admin %} - <h3>You are a SciPost Editorial Administrator.</h3> - {% endif %} - {% if is_advisory_board %} - <h3>You are a member of the Advisory Board.</h3> - {% endif %} - {% if is_editorial_college %} - <h3>You are a member of the Editorial College.</h3> - {% endif %} - {% if is_vetting_editor %} - <h3>You are a SciPost Vetting Editor.</h3> - {% endif %} - {% if is_registered_contributor %} - <h3>You are a Registered Contributor.</h3> - {% endif %} - {% if is_tester %} - <h3>You are a SciPost Tester.</h3> - {% endif %} - {% if is_ambassador %} - <h3>You are a SciPost Ambassador.</h3> - {% endif %} - {% if is_junior_ambassador %} - <h3>You are a SciPost Junior Ambassador.</h3> - {% endif %} - {% 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> - <li><a href="{% url 'scipost:update_personal_data' %}">Update your personal data</a></li> - <li><a href="{% url 'scipost:change_password' %}">Change your password</a></li> - </ul> - </div> - </div> - - {% if unavailability_form %} - <hr> - <div class="row"> - <div class="col"> - <h2 class="highlight">Your Availability</h2> - </div> - </div> - <div class="row justify-content-center"> - <div class="col-md-4 mr-md-5"> - <p>To help with the editorial workflow, you can inform us of any periods during which you are unavailable. We will do our best to respect these.</p> - <h3 class="mb-3">Mark a period as unavailable:</h3> - <form action="{% url 'scipost:mark_unavailable_period' %}" method="post"> - {% csrf_token %} - {{ unavailability_form|bootstrap }} - <input class="btn btn-secondary" type="submit" value="Submit" /> - </form> - </div> - <div class="col-md-4 ml-md-5"> - {% if unavailabilities %} - <h3>Your unavailability periods in our records</h3> - <p class="text-muted">(YYYY-MM-DD)</p> - <table class="table"> - <tr> - <th>Start</th> - <th colspan="2">End</th> - </tr> - {% for unav in unavailabilities %} - <tr> - <td>{{ unav.start }}</td> - <td>{{ unav.end }}</td> - <td> - <form action="{% url 'scipost:delete_unavailable_period' unav.id %}" method="post"> - {% csrf_token %} - <input class="btn btn-danger" type="submit" value="Delete" /> - </form> - </td> - </tr> - {% endfor %} - </table> - {% else %} - <p>You don't have any upcoming unavailability periods on record.</p> - {% endif %} - </div> - </div> - {% endif %} </div><!-- End tab --> {% 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"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Pending Editorial Actions</h2> - </div> - </div> - </div> - </div> - - <div class="row"> - {% 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> - {% if perms.scipost.can_vet_registration_requests %} - <li><a href="{% url 'scipost:vet_registration_requests' %}">Vet Registration requests</a> ({{ nr_reg_to_vet }})</li> - {% endif %} - {% if perms.scipost.can_resend_registration_requests %} - <li><a href="{% url 'scipost:registration_requests' %}">Awaiting validation</a> ({{ nr_reg_awaiting_validation }})</li> - {% endif %} - {% if perms.scipost.can_draft_registration_invitations %} - <li><a href="{% url 'scipost:draft_registration_invitation' %}">Draft a Registration Invitation</a></li> - {% endif %} - {% if perms.scipost.can_manage_registration_invitations %} - <li><a href="{% url 'scipost:registration_invitations' %}">Manage Registration Invitations</a></li> - {% endif %} - </ul> - - {% if perms.scipost.can_manage_registration_invitations %} - <h3>Notifications</h3> - <ul> - <li><a href="{% url 'scipost:citation_notifications' %}">Manage citation notifications</a></li> - </ul> - {% endif %} - - {% if is_scipost_admin %} - <h3>Email communications</h3> - <ul> - {% if perms.scipost.can_email_group_members %} - <li><a href="{% url 'scipost:email_group_members' %}">Email Group Members</a></li> - {% endif %} - {% if perms.scipost.can_email_particulars %} - <li><a href="{% url 'scipost:send_precooked_email' %}">Send a precooked email</a></li> - <li><a href="{% url 'scipost:email_particular' %}">Email a particular individual/address</a></li> - {% endif %} - {% if perms.scipost.can_manage_mailchimp %} - <li><a href="{% url 'mailing_lists:overview' %}">Manage mailing lists</a></li> - {% endif %} - </ul> - - <h3>SciPost Administation</h3> - <ul> - <li><a href="{% url 'affiliations:institutions' %}">Manage Institutions database</a></li> - </ul> - {% endif %} - - {% if perms.scipost.can_view_timesheets %} - <h3>Finance</h3> - <ul> - <li><a href="{% url 'finances:timesheets' %}">Production Team Timesheets</a></li> - </ul> - {% endif %} - </div> - {% endif %} - - <div class="col-md-4"> - {% if is_vetting_editor or perms.scipost.can_vet_submitted_reports %} - <h3>Vetting actions</h3> - <ul> - {% if perms.scipost.can_vet_commentary_requests %} - <li><a href="{% url 'commentaries:vet_commentary_requests' %}">Vet Commentary Page requests</a> ({{ nr_commentary_page_requests_to_vet }})</li> - {% endif %} - {% if perms.scipost.can_vet_comments %} - <li><a href="{% url 'comments:vet_submitted_comments_list' %}">Vet submitted Comments</a> ({{ nr_comments_to_vet }})</li> - {% endif %} - {% if perms.scipost.can_vet_thesislink_requests %} - <li><a href="{% url 'theses:unvetted_thesislinks' %}">Vet Thesis Link Requests</a> ({{ nr_thesislink_requests_to_vet }})</li> - {% endif %} - {% if perms.scipost.can_vet_authorship_claims %} - <li><a href="{% url 'scipost:vet_authorship_claims' %}">Vet Authorship Claims</a> ({{ nr_authorship_claims_to_vet }})</li> - {% endif %} - {% if perms.scipost.can_vet_submitted_reports %} - <li><a href="{% url 'submissions:vet_submitted_reports_list' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> - {% endif %} - </ul> - {% endif %} - - {% 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> - <li><a href="{% url 'submissions:pool' %}">Submissions Pool</a></li> - <li><a href="{% url 'submissions:treated_submissions_list' %}">Fully treated Submissions</a>{% if nr_treated_submissions_without_pdf %} ({{nr_treated_submissions_without_pdf}} unfinished){% endif %}</li> - <li><a href="{% url 'journals:harvest_citedby_list' %}">Harvest citedby data</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 '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 'proceedings:proceedings' %}">Manage Proceedings Issues</a></li> - </ul> - {% endif %} - - {% if perms.scipost.can_attend_VGMs %} - <h3>Virtual General Meetings</h3> - <ul> - <li><a href="{% url 'virtualmeetings:VGMs' %}">List of VGMs</a></li> - </ul> - {% endif %} - </div> - - {% if is_edcol_admin or is_editorial_college %} - <div class="col-md-4"> - <h3>Info</h3> - <ul> - <li><a href="{% url 'submissions:editorial_workflow' %}">How-to guide: summary of the editorial workflow</a></li> - </ul> - - <h3>Submissions assignments</h3> - <ul> - {% if perms.scipost.can_view_pool %} - <li><a href="{% url 'submissions:assignments' %}">Your assignments</a></li> - <li><a href="{% url 'scipost:Fellow_activity_overview' %}">View assignments overview</a></li> - {% endif %} - {% if perms.scipost.can_assign_submissions %} - <li>Assign Submissions via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_submissions_to_assign }})</li> - {% endif %} - {% if perms.scipost.can_take_charge_of_submissions %} - <li>Accept or decline assignments via the <a href="{% url 'submissions:pool' %}">Submissions Pool</a> ({{ nr_assignments_to_consider }})</li> - {% endif %} - </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 %} - </div> - - {% if active_assignments %} - <div class="row"> - <div class="col-12"> - <h3 class="highlight">Submissions for which you are Editor-in-charge</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for assignment in active_assignments %} - <li class="list-group-item"> - <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> - </div> - </div> - {% endif %} </div><!-- End tab --> {% endif %} {% if contributor %} - {# If user is contributor #} + {# If user is contributor #} <!-- Tab: Publications --> <div class="tab-pane" id="publications" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title">Publications</h2> - <ul class="mb-0"> - {% if nr_publication_authorships_to_claim > 0 %} - <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_publication_authorships_to_claim}})</a></li> - {% endif %} - </ul> - </div> - </div> - </div> - </div> - - {# {% if own_publications %}#} - <div class="row" id="mypublicationslist"> - <div class="col-12"> - <h3 class="mb-3">Publications for which you are identified as an author:</h3> - </div> - <div class="col-12"> - <ul class="list-unstyled"> - {% for pub in own_publications %} - <li> - <div class="card card-grey card-publication" id="{{pub.doi_label}}"> - {% include 'journals/_publication_card_content.html' with publication=pub current_user=request.user %} - </div> - </li> - {% empty %} - <li> - <em>No Publications found</em> - </li> - {% endfor %} - </ul> - </div> - </div> - {# {% endif %}#} </div><!-- End tab --> - {% if perms.scipost.can_referee %} + {% if perms.scipost.can_referee %} <!-- Tab: Refereeing --> <div class="tab-pane" id="refereeing" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title">Refereeing Tasks</h2> - <ul class="mb-0"> - <li><a href="{% url 'submissions:accept_or_decline_ref_invitations' %}">Accept/decline refereeing invitations</a> ({{ nr_ref_inv_to_consider }})</li> - </ul> - </div> - </div> - </div> - </div> - - <div class="row"> - <div class="col-12"> - <h3>Pending Refereeing Tasks:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for task in pending_ref_tasks %} - <li class="list-group-item"> - <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> - {% endfor %} - </ul> - </div> - </div> - - {% if contributor.reports.in_draft.exists %} - <div class="row"> - <div class="col-12"> - <h3>Unfinished reports:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for report in contributor.reports.in_draft.all %} - <li class="list-group-item"> - <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> - </div> - </div> - {% endif %} - - {% if contributor.reports.non_draft.exists %} - <div class="row"> - <div class="col-12"> - <h3>Finished reports:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for report in contributor.reports.non_draft.all %} - <li class="list-group-item"> - {% 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 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> - <th style='min-width: 100px;'>Received:</th><td>{{ report.date_submitted|date:'Y-n-j' }}<td> - </tr> - <tr> - <th>Status:</th><td {% if report.status == 'vetted' %}class="text-success"{% elif report.status == 'unvetted' %}class="text-danger"{% endif %}>{{report.get_status_display}}</td> - </tr> - {% if report.doi_label %} - <tr> - <th>DOI:</th><td>{{ report.doi_string }}</td></th> - {% endif %} - <tr> - <th>Anonymous:</th><td>{{report.anonymous|yesno:'Yes,No'}}</td>{% if report.anonymous %}<td>You can <a href="{% url 'journals:sign_existing_report' report_id=report.id %}">click here to sign this Report</a> (leads to confirmation page){% endif %}</td> - </tr> - </table> - </div> - </li> - {% endfor %} - </ul> - </div> - </div> - {% endif %} </div><!-- End tab --> {% endif %} <!-- Tab: Submissions --> <div class="tab-pane" id="submissions" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title">Submissions</h2> - <ul class="mb-0"> - {% if nr_submission_authorships_to_claim > 0 %} - <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_submission_authorships_to_claim}})</a></li> - {% endif %} - <li><a href="{% url 'submissions:submit_manuscript' %}">Submit an arXiv preprint to a SciPost Journal</a></li> - </ul> - </div> - </div> - </div> - </div> - - {# {% if own_submissions %}#} - <div class="row" id="mysubmissionslist"> - <div class="col-12"> - <h3>Submissions for which you are identified as an author:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for sub in own_submissions %} - <li class="list-group-item"> - <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"> - <em>No Submissions found</em> - </li> - {% endfor %} - </ul> - </div> - </div> - {# {% endif %}#} </div><!-- End tab --> <!-- Tab: Commentaries --> <div class="tab-pane" id="commentaries" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title">Commentaries</h2> - <ul class="mb-0"> - {% if nr_commentary_authorships_to_claim > 0 %} - <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_commentary_authorships_to_claim}})</a></li> - {% endif %} - <li><a href="{% url 'commentaries:request_commentary' %}">Request opening a SciPost Commentary Page</a></li> - </ul> - </div> - </div> - </div> - </div> - - <div class="row" id="mycommentarieslist"> - <div class="col-12"> - <h3>Commentaries for which you are identified as an author:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for com in own_commentaries %} - <li class="list-group-item"> - {% include 'commentaries/_commentary_card_content.html' with commentary=com %} - </li> - {% empty %} - <li class="list-group-item"><em>No Commentaries found</em></li> - {% endfor %} - </ul> - </div> - </div> </div><!-- End tab --> <!-- Tab: Theses --> <div class="tab-pane" id="theses" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title">Theses</h2> - <ul class="mb-0"> - {% if nr_thesis_authorships_to_claim > 0 %} - <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_thesis_authorships_to_claim}})</a></li> - {% endif %} - <li><a href="{% url 'theses:request_thesislink' %}">Request a SciPost ThesisLink</a></li> - </ul> - </div> - </div> - </div> - </div> - - <div class="row" id="mytheseslist"> - <div class="col-12"> - <h3>Theses for which you are identified as an author:</h3> - </div> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for thesis in own_thesislinks %} - <li class="list-group-item"> - {% include 'theses/_thesislink_card_content.html' with thesislink=thesis %} - </li> - {% empty %} - <li class="list-group-item"><em>No Theses found</em></li> - {% endfor %} - </ul> - </div> - </div> - </div><!-- End tab --> <!-- Tab: Comments --> <div class="tab-pane" id="comments" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Your Comments</h2> - </div> - </div> - </div> - </div> - - <div class="row" id="mycommentslist"> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for own_comment in own_comments %} - <li class="list-group-item"> - {% include 'comments/_comment_card_extended_for_author.html' with comment=own_comment %} - </li> - {% empty %} - <li class="list-group-item"><em>You have not commented yet.</em></li> - {% endfor %} - </ul> - </div> - </div> </div><!-- End tab --> <!-- Tab: Author Replies --> <div class="tab-pane" id="author-replies" role="tabpanel"> - <div class="row"> - <div class="col-12"> - <div class="card card-grey"> - <div class="card-body"> - <h2 class="card-title mb-0">Your Author Replies</h2> - </div> - </div> - </div> - </div> - - <div class="row" id="myauthorreplieslist"> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for own_reply in own_authorreplies %} - <li class="list-group-item"> - {% include 'comments/_comment_card_extended_for_author.html' with comment=own_reply %} - </li> - {% empty %} - <li class="list-group-item"><em>You do not have Author Replies yet.</em></li> - {% endfor %} - </ul> - </div> - </div> </div><!-- End tab --> {# END: If user is contributor #} diff --git a/scipost/templates/scipost/register.html b/scipost/templates/scipost/register.html index a5420ffc90fc8d85344482980f288d4ccd8d9ebc..f8901f6fcf477d00619a0b5babc584f02b6d4795 100644 --- a/scipost/templates/scipost/register.html +++ b/scipost/templates/scipost/register.html @@ -4,11 +4,18 @@ {% block pagetitle %}: register{% endblock pagetitle %} +{% block breadcrumb %} + <div class="container-outside header"> + <div class="container"> + <h1>Register to SciPost</h1> + </div> + </div> +{% endblock %} + {% block content %} <div class="row"> <div class="col-12"> - <h1 class="highlight">Register to SciPost</h1> {% if invitation %} <h2>Welcome {{invitation.get_title_display}} {{invitation.last_name}} and thanks in advance for registering (by completing this form)</h2> {% endif %} @@ -17,7 +24,7 @@ <div class="row"> <div class="col-md-4 mb-md-2"> - <div class="card card-outline-secondary"> + <div class="card bg-white"> <div class="card-body"> <h3>Notes:</h3> <p class="text-danger"><em>Only professional academics (staff members, postdocs, PhD students) can register!</em></p> diff --git a/scipost/urls.py b/scipost/urls.py index 3389075ecd634d4edeeecb7fc0f6a3522f58c16d..3c8fb02160d11ca9f26401a791166ca34be9bffb 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -124,13 +124,33 @@ urlpatterns = [ # Authentication url(r'^login/$', views.login_view, name='login'), url(r'^logout$', views.logout_view, name='logout'), - url(r'^personal_page$', views.personal_page, name='personal_page'), url(r'^change_password$', views.change_password, name='change_password'), url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', views.reset_password_confirm, name='reset_password_confirm'), url(r'^reset_password/$', views.reset_password, name='reset_password'), url(r'^update_personal_data$', views.update_personal_data, name='update_personal_data'), + # Personal Page + url(r'^personal_page/$', views.personal_page, name='personal_page'), + url(r'^personal_page/account$', views.personal_page, + name='personal_page_account', kwargs={'tab': 'account'}), + url(r'^personal_page/editorial_actions$', views.personal_page, + name='personal_page_editorial_actions', kwargs={'tab': 'editorial_actions'}), + url(r'^personal_page/refereeing$', views.personal_page, + name='personal_page_refereeing', kwargs={'tab': 'refereeing'}), + url(r'^personal_page/publications$', views.personal_page, + name='personal_page_publications', kwargs={'tab': 'publications'}), + url(r'^personal_page/submissions$', views.personal_page, + name='personal_page_submissions', kwargs={'tab': 'submissions'}), + url(r'^personal_page/commentaries$', views.personal_page, + name='personal_page_commentaries', kwargs={'tab': 'commentaries'}), + url(r'^personal_page/theses$', views.personal_page, + name='personal_page_theses', kwargs={'tab': 'theses'}), + url(r'^personal_page/comments$', views.personal_page, + name='personal_page_comments', kwargs={'tab': 'comments'}), + url(r'^personal_page/author_replies$', views.personal_page, + name='personal_page_author_replies', kwargs={'tab': 'author_replies'}), + # Unavailabilities url(r'^unavailable_period$', views.mark_unavailable_period, name='mark_unavailable_period'), url(r'^unavailable_period/(?P<period_id>[0-9]+)/delete$', views.delete_unavailable_period, @@ -174,6 +194,30 @@ urlpatterns = [ # Publications # ################ + # Reports + url(r'^(?P<doi_label>SciPost.Report.[0-9]+)$', + journals_views.report_detail, + name='report_detail'), + url(r'^10.21468/(?P<doi_label>SciPost.Report.[0-9]+)$', + journals_views.report_detail, + name='report_detail'), + + # Comments + url(r'^(?P<doi_label>SciPost.Comment.[0-9]+)$', + journals_views.comment_detail, + name='comment_detail'), + url(r'^10.21468/(?P<doi_label>SciPost.Comment.[0-9]+)$', + journals_views.comment_detail, + name='comment_detail'), + + # Author Replies + url(r'^(?P<doi_label>SciPost.AuthorReply.[0-9]+)$', + journals_views.author_reply_detail, + name='author_reply_detail'), + url(r'^10.21468/(?P<doi_label>SciPost.AuthorReply.[0-9]+)$', + journals_views.author_reply_detail, + name='author_reply_detail'), + # Publication detail (+pdf) url(r'^10.21468/(?P<doi_label>[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', journals_views.publication_detail, diff --git a/scipost/views.py b/scipost/views.py index a9fe527bf5667f0f4f2368b966a3ca8c66dc58a7..f370969ba51a399f604980fd9005c591be154a8c 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -9,6 +9,7 @@ from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.models import Group from django.contrib.auth.views import password_reset, password_reset_confirm from django.core import mail +from django.core.exceptions import PermissionDenied from django.core.mail import EmailMessage, EmailMultiAlternatives from django.core.paginator import Paginator from django.core.urlresolvers import reverse @@ -715,14 +716,216 @@ def delete_unavailable_period(request, period_id): @login_required -def personal_page(request): +@user_passes_test(has_contributor) +def _personal_page_editorial_account(request): + """ + The Personal Page tab: Account + """ + contributor = request.user.contributor + context = { + 'contributor': contributor, + 'unavailability_form': UnavailabilityPeriodForm(), + 'unavailabilities': contributor.unavailability_periods.future().order_by('start') + } + return render(request, 'partials/scipost/personal_page/account.html', context) + + +@user_passes_test(has_contributor) +def _personal_page_editorial_actions(request): + """ + The Personal Page tab: Editorial Actions + """ + permission = request.user.groups.filter(name__in=[ + 'Ambassadors', + 'Advisory Board', + 'Editorial Administrators', + 'Editorial College', + 'Vetting Editors', + 'Junior Ambassadors']).exists() + + if not permission: + raise PermissionDenied + + context = {} + contributor = request.user.contributor + + if contributor.is_SP_Admin(): + # count the number of pending registration requests + context['nr_reg_to_vet'] = Contributor.objects.awaiting_vetting().count() + context['nr_reg_awaiting_validation'] = Contributor.objects.awaiting_validation().count() + context['nr_submissions_to_assign'] = Submission.objects.prescreening().count() + context['nr_recommendations_to_prepare_for_voting'] = EICRecommendation.objects.filter( + submission__status='voting_in_preparation').count() + + if contributor.is_VE(): + context['nr_commentary_page_requests_to_vet'] = (Commentary.objects.awaiting_vetting() + .exclude(requested_by=contributor).count()) + context['nr_comments_to_vet'] = Comment.objects.awaiting_vetting().count() + context['nr_thesislink_requests_to_vet'] = ThesisLink.objects.awaiting_vetting().count() + context['nr_authorship_claims_to_vet'] = AuthorshipClaim.objects.awaiting_vetting().count() + + if contributor.is_MEC(): + context['nr_assignments_to_consider'] = contributor.editorial_assignments.open().count() + context['active_assignments'] = contributor.editorial_assignments.ongoing() + context['nr_reports_to_vet'] = Report.objects.awaiting_vetting().filter( + submission__editor_in_charge=contributor).count() + + if contributor.is_EdCol_Admin(): + context['nr_reports_without_pdf'] = Report.objects.accepted().filter(pdf_report='').count() + context['nr_treated_submissions_without_pdf'] = Submission.objects.treated().filter( + pdf_refereeing_pack='').count() + + return render(request, 'partials/scipost/personal_page/editorial_actions.html', context) + + +@permission_required('scipost.can_referee', return_403=True) +@user_passes_test(has_contributor) +def _personal_page_refereeing(request): + """ + The Personal Page tab: Refereeing + """ + context = { + 'contributor': request.user.contributor + } + return render(request, 'partials/scipost/personal_page/refereeing.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_publications(request): + """ + The Personal Page tab: Publications + """ + contributor = request.user.contributor + context = { + 'contributor': contributor, + 'own_publications': contributor.publications.order_by('-publication_date') + } + context['nr_publication_authorships_to_claim'] = Publication.objects.filter( + author_list__contains=request.user.last_name).exclude( + authors=contributor).exclude( + authors_claims=contributor).exclude( + authors_false_claims=contributor).count() + return render(request, 'partials/scipost/personal_page/publications.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_submissions(request): + """ + The Personal Page tab: Submissions + """ + contributor = request.user.contributor + context = {'contributor': contributor} + + context['nr_submission_authorships_to_claim'] = Submission.objects.filter( + author_list__contains=request.user.last_name).exclude( + authors=contributor).exclude( + authors_claims=contributor).exclude( + authors_false_claims=contributor).count() + context['own_submissions'] = contributor.submissions.filter( + is_current=True).order_by('-submission_date') + return render(request, 'partials/scipost/personal_page/submissions.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_commentaries(request): + """ + The Personal Page tab: Commentaries + """ + contributor = request.user.contributor + context = {'contributor': contributor} + + context['nr_commentary_authorships_to_claim'] = Commentary.objects.filter( + author_list__contains=request.user.last_name).exclude( + authors=contributor).exclude( + authors_claims=contributor).exclude( + authors_false_claims=contributor).count() + context['own_submissions'] = contributor.commentaries.order_by('-latest_activity') + return render(request, 'partials/scipost/personal_page/commentaries.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_theses(request): + """ + The Personal Page tab: Theses + """ + contributor = request.user.contributor + context = {'contributor': contributor} + + context['nr_thesis_authorships_to_claim'] = ThesisLink.objects.filter( + author__contains=request.user.last_name).exclude( + author_as_cont=contributor).exclude( + author_claims=contributor).exclude( + author_false_claims=contributor).count() + context['own_thesislinks'] = contributor.theses.all() + return render(request, 'partials/scipost/personal_page/theses.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_comments(request): + """ + The Personal Page tab: Comments + """ + contributor = request.user.contributor + context = { + 'contributor': contributor, + 'own_comments': contributor.comments.regular_comments().order_by('-date_submitted') + } + + return render(request, 'partials/scipost/personal_page/comments.html', context) + + +@login_required +@user_passes_test(has_contributor) +def _personal_page_author_replies(request): + """ + The Personal Page tab: Author Replies + """ + contributor = request.user.contributor + context = { + 'contributor': contributor, + 'own_authorreplies': contributor.comments.author_replies().order_by('-date_submitted'), + } + + return render(request, 'partials/scipost/personal_page/author_replies.html', context) + + +@login_required +def personal_page(request, tab='account'): """ The Personal Page is the main view for accessing user functions. """ + if request.is_ajax(): + if tab == 'account': + return _personal_page_editorial_account(request) + elif tab == 'editorial_actions': + return _personal_page_editorial_actions(request) + elif tab == 'refereeing': + return _personal_page_refereeing(request) + elif tab == 'publications': + return _personal_page_publications(request) + elif tab == 'submissions': + return _personal_page_submissions(request) + elif tab == 'commentaries': + return _personal_page_commentaries(request) + elif tab == 'theses': + return _personal_page_theses(request) + elif tab == 'comments': + return _personal_page_comments(request) + elif tab == 'author_replies': + return _personal_page_author_replies(request) + raise Http404 + context = { 'appellation': str(request.user), 'needs_validation': False, + 'tab': tab, } + try: contributor = Contributor.objects.select_related('user').get(user=request.user) context['needs_validation'] = contributor.status != CONTRIBUTOR_NORMAL @@ -730,127 +933,14 @@ def personal_page(request): contributor = None if contributor: - # Compile the unavailability periods: - now = timezone.now() - unavailabilities = contributor.unavailability_periods.exclude(end__lt=now).order_by('start') - unavailability_form = UnavailabilityPeriodForm() - - # if an editor, count the number of actions required: - nr_reg_to_vet = 0 - nr_reg_awaiting_validation = 0 - nr_submissions_to_assign = 0 - nr_recommendations_to_prepare_for_voting = 0 - if contributor.is_SP_Admin(): - # count the number of pending registration requests - nr_reg_to_vet = Contributor.objects.awaiting_vetting().count() - nr_reg_awaiting_validation = (Contributor.objects.awaiting_validation() - .count()) - nr_submissions_to_assign = Submission.objects.prescreening().count() - nr_recommendations_to_prepare_for_voting = EICRecommendation.objects.filter( - submission__status='voting_in_preparation').count() - - nr_assignments_to_consider = 0 - active_assignments = None - nr_reports_to_vet = 0 - if contributor.is_MEC(): - nr_assignments_to_consider = (contributor.editorial_assignments - .open().count()) - active_assignments = contributor.editorial_assignments.ongoing() - nr_reports_to_vet = (Report.objects.awaiting_vetting() - .filter(submission__editor_in_charge=contributor).count()) - - nr_commentary_page_requests_to_vet = 0 - nr_comments_to_vet = 0 - nr_thesislink_requests_to_vet = 0 - nr_authorship_claims_to_vet = 0 - if contributor.is_VE(): - nr_commentary_page_requests_to_vet = (Commentary.objects.awaiting_vetting() - .exclude(requested_by=contributor).count()) - nr_comments_to_vet = Comment.objects.awaiting_vetting().count() - nr_thesislink_requests_to_vet = ThesisLink.objects.awaiting_vetting().count() - nr_authorship_claims_to_vet = AuthorshipClaim.objects.awaiting_vetting().count() - # Refereeing - nr_ref_inv_to_consider = contributor.referee_invitations.open().count() - pending_ref_tasks = contributor.referee_invitations.in_process() - refereeing_tab_total_count = nr_ref_inv_to_consider + len(pending_ref_tasks) + refereeing_tab_total_count = contributor.referee_invitations.open().count() + refereeing_tab_total_count += contributor.referee_invitations.in_process().count() refereeing_tab_total_count += contributor.reports.in_draft().count() - # Verify if there exist objects authored by this contributor, - # whose authorship hasn't been claimed yet - own_publications = contributor.publications.order_by('-publication_date') - own_submissions = contributor.submissions.filter(is_current=True).order_by('-submission_date') - own_commentaries = contributor.commentaries.order_by('-latest_activity') - own_thesislinks = contributor.theses.all() - nr_publication_authorships_to_claim = (Publication.objects.filter( - author_list__contains=contributor.user.last_name) - .exclude(authors=contributor) - .exclude(authors_claims=contributor) - .exclude(authors_false_claims=contributor) - .count()) - nr_submission_authorships_to_claim = (Submission.objects.filter( - author_list__contains=contributor.user.last_name) - .exclude(authors=contributor) - .exclude(authors_claims=contributor) - .exclude(authors_false_claims=contributor) - .count()) - nr_commentary_authorships_to_claim = (Commentary.objects.filter( - author_list__contains=contributor.user.last_name) - .exclude(authors=contributor) - .exclude(authors_claims=contributor) - .exclude(authors_false_claims=contributor) - .count()) - nr_thesis_authorships_to_claim = (ThesisLink.objects.filter( - author__contains=contributor.user.last_name) - .exclude(author_as_cont=contributor) - .exclude(author_claims=contributor) - .exclude(author_false_claims=contributor) - .count()) - own_comments = (contributor.comments.regular_comments() - .select_related('author', 'submission') - .order_by('-date_submitted')) - own_authorreplies = (contributor.comments.author_replies() - .order_by('-date_submitted')) - - appellation = contributor.get_title_display() + ' ' + contributor.user.last_name - - context.update({ - 'contributor': contributor, - 'appellation': appellation, - 'unavailabilities': unavailabilities, - 'unavailability_form': unavailability_form, - 'nr_reg_to_vet': nr_reg_to_vet, - 'nr_reg_awaiting_validation': nr_reg_awaiting_validation, - 'nr_commentary_page_requests_to_vet': nr_commentary_page_requests_to_vet, - 'nr_comments_to_vet': nr_comments_to_vet, - 'nr_thesislink_requests_to_vet': nr_thesislink_requests_to_vet, - 'nr_authorship_claims_to_vet': nr_authorship_claims_to_vet, - 'nr_reports_to_vet': nr_reports_to_vet, - 'nr_submissions_to_assign': nr_submissions_to_assign, - 'nr_recommendations_to_prepare_for_voting': nr_recommendations_to_prepare_for_voting, - 'nr_assignments_to_consider': nr_assignments_to_consider, - 'active_assignments': active_assignments, - 'nr_publication_authorships_to_claim': nr_publication_authorships_to_claim, - 'nr_submission_authorships_to_claim': nr_submission_authorships_to_claim, - 'nr_commentary_authorships_to_claim': nr_commentary_authorships_to_claim, - 'nr_thesis_authorships_to_claim': nr_thesis_authorships_to_claim, - 'nr_ref_inv_to_consider': nr_ref_inv_to_consider, - 'pending_ref_tasks': pending_ref_tasks, - 'refereeing_tab_total_count': refereeing_tab_total_count, - 'own_publications': own_publications, - 'own_submissions': own_submissions, - 'own_commentaries': own_commentaries, - 'own_thesislinks': own_thesislinks, - 'own_comments': own_comments, - 'own_authorreplies': own_authorreplies, - }) - - # Only add variables if user has right permission - if request.user.has_perm('scipost.can_manage_reports'): - context['nr_reports_without_pdf'] = (Report.objects.accepted() - .filter(pdf_report='').count()) - context['nr_treated_submissions_without_pdf'] = (Submission.objects.treated() - .filter(pdf_refereeing_pack='').count()) + context['refereeing_tab_total_count'] = refereeing_tab_total_count + context['appellation'] = contributor.get_title_display() + ' ' + contributor.user.last_name + context['contributor'] = contributor return render(request, 'scipost/personal_page.html', context) diff --git a/stats/templates/stats/statistics.html b/stats/templates/stats/statistics.html index afe2e43169338f2304e354f5c728868913baa7e2..61fa1a21de5800c7f380a3937c80e4ad18dcd890 100644 --- a/stats/templates/stats/statistics.html +++ b/stats/templates/stats/statistics.html @@ -56,6 +56,7 @@ {% else %} <th>Nr publications</th> <th>Duration average</th> + <th>Citation rate (per paper per year)</ht> {% endif %} </tr> <tr> @@ -63,10 +64,12 @@ <td>{{ issue.doi_label }}</td> <td>{{ issue|issue_nr_publications }}</td> <td>{{ issue|issue_avg_processing_duration|floatformat:2 }} days</td> + <td>{{ issue|issue_citation_rate|floatformat:2 }}</td> {% elif volume %} <td>{{ volume.doi_label }}</td> <td>{{ volume|volume_nr_publications }}</td> <td>{{ volume|volume_avg_processing_duration|floatformat:2 }} days</td> + <td>{{ volume|volume_citation_rate|floatformat:2 }}</td> {% else %} <td>{{ journal.doi_label }}</td> {% if year %} @@ -80,6 +83,7 @@ {% else %} <td>{{ journal|journal_nr_publications }}</td> <td>{{ journal|journal_avg_processing_duration|floatformat:2 }} days</td> + <td>{{ journal|journal_citation_rate|floatformat:2 }}</td> {% endif %} {% endif %} </tr> diff --git a/stats/templatetags/stats_extras.py b/stats/templatetags/stats_extras.py index 9c5c6e636f86716021b322f4c66afe2090b2a294..d6362255440acb8a9f2a27db5fd665b2bc8f2c55 100644 --- a/stats/templatetags/stats_extras.py +++ b/stats/templatetags/stats_extras.py @@ -31,7 +31,6 @@ def journal_publication_years(journal): def journal_nr_publications(journal): return Publication.objects.filter(in_issue__in_volume__in_journal=journal).count() - @register.filter(name='journal_avg_processing_duration') def journal_avg_processing_duration(journal): duration = Publication.objects.filter( @@ -40,12 +39,15 @@ def journal_avg_processing_duration(journal): if not duration: return 0 return duration.days + duration.seconds/86400 +@register.filter(name='journal_citation_rate') +def journal_citation_rate(journal): + return journal.citation_rate() + @register.filter(name='volume_nr_publications') def volume_nr_publications(volume): return Publication.objects.filter(in_issue__in_volume=volume).count() - @register.filter(name='volume_avg_processing_duration') def volume_avg_processing_duration(volume): duration = Publication.objects.filter( @@ -54,12 +56,15 @@ def volume_avg_processing_duration(volume): if not duration: return 0 return duration.days + duration.seconds/86400 +@register.filter(name='volume_citation_rate') +def volume_citation_rate(volume): + return volume.citation_rate() + @register.filter(name='issue_nr_publications') def issue_nr_publications(issue): return Publication.objects.filter(in_issue=issue).count() - @register.filter(name='issue_avg_processing_duration') def issue_avg_processing_duration(issue): duration = Publication.objects.filter( @@ -67,3 +72,7 @@ def issue_avg_processing_duration(issue): avg=Avg(F('publication_date') - F('submission_date')))['avg'] if not duration: return 0 return duration.days + duration.seconds/86400 + +@register.filter(name='issue_citation_rate') +def issue_citation_rate(issue): + return issue.citation_rate() diff --git a/stats/views.py b/stats/views.py index 3b3ac22ac7d4c29fcb6271d184c53ddc905e1210..11d7bd845e11df31b0c12fc591974163be366f78 100644 --- a/stats/views.py +++ b/stats/views.py @@ -8,7 +8,7 @@ from journals.models import Journal, Volume, Issue, Publication from submissions.models import Submission -@permission_required('scipost.can_oversee_refereeing', raise_exception=True) +@permission_required('scipost.can_view_statistics', raise_exception=True) def statistics(request, journal_doi_label=None, volume_nr=None, issue_nr=None, year=None): journals = Journal.objects.all() context = { diff --git a/submissions/admin.py b/submissions/admin.py index 0f52fe45e9c9a0c93e0579f4b2e6f1ce8ca05596..0466fba0ced8fc05b6e32063d5ef07e9deb1ed97 100644 --- a/submissions/admin.py +++ b/submissions/admin.py @@ -184,7 +184,7 @@ class ReportAdminForm(forms.ModelForm): class ReportAdmin(admin.ModelAdmin): search_fields = ['author__user__last_name', 'submission'] - list_display = ('author', 'status', submission_short_title, 'date_submitted', ) + list_display = ('author', 'status', 'doi_label', submission_short_title, 'date_submitted', ) list_display_links = ('author',) date_hierarchy = 'date_submitted' list_filter = ('status',) diff --git a/submissions/constants.py b/submissions/constants.py index 355621e77004c12a8dab18633e2e5ca5c7da8add..17c831be66310b27573f442daf071a54fd48af26 100644 --- a/submissions/constants.py +++ b/submissions/constants.py @@ -113,7 +113,7 @@ ED_COMM_CHOICES = ( ('EtoR', 'Editor-in-charge to Referee'), ('EtoS', 'Editor-in-charge to SciPost Editorial Administration'), ('AtoE', 'Author to Editor-in-charge'), - ('RtoE', 'Referee to Editor-in-Charge'), + ('RtoE', 'Referee to Editor-in-charge'), ('StoE', 'SciPost Editorial Administration to Editor-in-charge'), ) @@ -164,7 +164,7 @@ RANKING_CHOICES = ( REPORT_REC = ( (None, '-'), - (1, 'Publish as Tier I (top 10% of papers in this journal, qualifies as Select) NOTE: SELECT NOT YET OPEN, STARTS EARLY 2017'), + (1, 'Publish as Tier I (top 10% of papers in this journal, qualifies as Select)'), (2, 'Publish as Tier II (top 50% of papers in this journal)'), (3, 'Publish as Tier III (meets the criteria of this journal)'), (-1, 'Ask for minor revision'), diff --git a/submissions/forms.py b/submissions/forms.py index 2de2fca2daf2ef4208e8565a826d8a3b0f316025..8d8fa809847e1fb5fc2c33f1cd4d056af1824a57 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -188,7 +188,7 @@ class SubmissionChecks: class SubmissionIdentifierForm(SubmissionChecks, forms.Form): - IDENTIFIER_PATTERN_NEW = r'^[0-9]{4,}.[0-9]{4,5}v[0-9]{1,2}$' + IDENTIFIER_PATTERN_NEW = r'^[0-9]{4,}\.[0-9]{4,5}v[0-9]{1,2}$' IDENTIFIER_PLACEHOLDER = 'new style (with version nr) ####.####(#)v#(#)' identifier = forms.RegexField(regex=IDENTIFIER_PATTERN_NEW, strip=True, @@ -602,10 +602,9 @@ class ReportForm(forms.ModelForm): report.status = STATUS_UNVETTED # Update invitation and report meta data if exist - invitation = self.submission.referee_invitations.filter(referee=report.author).first() - if invitation: - invitation.fulfilled = True - invitation.save() + updated_invitations = self.submission.referee_invitations.filter( + referee=report.author).update(fulfilled=True) + if updated_invitations > 0: report.invited = True # Check if report author if the report is being flagged on the submission @@ -826,7 +825,7 @@ class iThenticateReportForm(forms.ModelForm): client = self.client response = client.documents.get(self.document_id) if response['status'] == 200: - return response.get('data')[0].get('documents') + return response.get('data')[0].get('documents')[0] self.add_error(None, "Updating failed. iThenticate didn't return valid data [1]") for msg in client.messages: diff --git a/submissions/managers.py b/submissions/managers.py index 021daa46a5a214d085a4a1faa3ba7890e14b3ff7..20b455d39e4a976872434f2fe05a23abdd23c572 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -320,6 +320,9 @@ class ReportQuerySet(models.QuerySet): class RefereeInvitationQuerySet(models.QuerySet): + def awaiting_response(self): + return self.pending().open() + def pending(self): return self.filter(accepted=None) @@ -348,3 +351,8 @@ class RefereeInvitationQuerySet(models.QuerySet): deadline = now qs = qs.filter(submission__reporting_deadline__lte=deadline) return qs + + +class EditorialCommunicationQueryset(models.QuerySet): + def for_referees(self): + return self.filter(comtype__in=['EtoR', 'RtoE']) diff --git a/submissions/migrations/0002_auto_20180118_1033.py b/submissions/migrations/0002_auto_20180118_1033.py new file mode 100644 index 0000000000000000000000000000000000000000..d4e1758aebb750e181a711cbf7cebe74e6a0875f --- /dev/null +++ b/submissions/migrations/0002_auto_20180118_1033.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-18 09:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='eicrecommendation', + name='recommendation', + field=models.SmallIntegerField(choices=[(None, '-'), (1, 'Publish as Tier I (top 10% of papers in this journal, qualifies as Select)'), (2, 'Publish as Tier II (top 50% of papers in this journal)'), (3, 'Publish as Tier III (meets the criteria of this journal)'), (-1, 'Ask for minor revision'), (-2, 'Ask for major revision'), (-3, 'Reject')]), + ), + migrations.AlterField( + model_name='report', + name='recommendation', + field=models.SmallIntegerField(choices=[(None, '-'), (1, 'Publish as Tier I (top 10% of papers in this journal, qualifies as Select)'), (2, 'Publish as Tier II (top 50% of papers in this journal)'), (3, 'Publish as Tier III (meets the criteria of this journal)'), (-1, 'Ask for minor revision'), (-2, 'Ask for major revision'), (-3, 'Reject')]), + ), + ] diff --git a/submissions/migrations/0003_auto_20180120_1102.py b/submissions/migrations/0003_auto_20180120_1102.py new file mode 100644 index 0000000000000000000000000000000000000000..1f921da764c7b7ba6b30595a24a7587555787853 --- /dev/null +++ b/submissions/migrations/0003_auto_20180120_1102.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-20 10:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0002_auto_20180118_1033'), + ] + + operations = [ + migrations.AlterField( + model_name='editorialcommunication', + name='comtype', + field=models.CharField(choices=[('EtoA', 'Editor-in-charge to Author'), ('EtoR', 'Editor-in-charge to Referee'), ('EtoS', 'Editor-in-charge to SciPost Editorial Administration'), ('AtoE', 'Author to Editor-in-charge'), ('RtoE', 'Referee to Editor-in-charge'), ('StoE', 'SciPost Editorial Administration to Editor-in-charge')], max_length=4), + ), + migrations.AlterField( + model_name='editorialcommunication', + name='referee', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='editorial_communications', to='scipost.Contributor'), + ), + ] diff --git a/submissions/models.py b/submissions/models.py index 682f837dd60520183ac0e6d016efd64fea361808..00a262f1e6d06c835cf0cd5e28822ebbbe950df2 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -15,9 +15,10 @@ 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,\ - REPORT_TYPES, REPORT_NORMAL + REPORT_TYPES, REPORT_NORMAL, STATUS_DRAFT, STATUS_VETTED from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationQuerySet,\ - ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet + ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet,\ + EditorialCommunicationQueryset from .utils import ShortSubmissionCycle, DirectRecommendationSubmissionCycle,\ GeneralSubmissionCycle @@ -361,6 +362,10 @@ class RefereeInvitation(SubmissionRelatedObjectMixin, models.Model): def notification_name(self): return self.submission.arxiv_identifier_w_vn_nr + @property + def related_report(self): + return self.submission.reports.filter(author=self.referee).first() + def reset_content(self): self.nr_reminders = 0 self.date_last_reminded = None @@ -454,6 +459,14 @@ class Report(SubmissionRelatedObjectMixin, models.Model): return (self.author.user.first_name + ' ' + self.author.user.last_name + ' on ' + self.submission.title[:50] + ' by ' + self.submission.author_list[:50]) + @property + def is_in_draft(self): + return self.status == STATUS_DRAFT + + @property + def is_vetted(self): + return self.status == STATUS_VETTED + def save(self, *args, **kwargs): # Control Report count per Submission. if not self.report_nr: @@ -475,8 +488,7 @@ class Report(SubmissionRelatedObjectMixin, models.Model): def doi_string(self): if self.doi_label: return '10.21468/' + self.doi_label - else: - return None + return '' @cached_property def title(self): @@ -486,7 +498,7 @@ class Report(SubmissionRelatedObjectMixin, models.Model): """ return self.submission.title - @cached_property + @property def is_followup_report(self): """ Check if current Report is a `FollowupReport`. A Report is a `FollowupReport` if the @@ -496,6 +508,16 @@ class Report(SubmissionRelatedObjectMixin, models.Model): 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 save(self, *args, **kwargs): + # Control Report count per Submission. + if not self.report_nr: + self.report_nr = self.submission.reports.count() + 1 + return super().save(*args, **kwargs) + + def create_doi_label(self): + self.doi_label = 'SciPost.Report.' + str(self.id) + self.save() + def latest_report_from_series(self): """ Get latest Report from the same author for the Submission series. @@ -505,6 +527,55 @@ class Report(SubmissionRelatedObjectMixin, models.Model): .order_by('submission__arxiv_identifier_wo_vn_nr').last()) + @property + def associated_published_doi(self): + """ + Check if the Report relates to a SciPost-published object. + If it is, return the doi of the published object. + """ + try: + publication = Publication.objects.get( + accepted_submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr) + except Publication.DoesNotExist: + return None + return publication.doi_string + + @property + def relation_to_published(self): + """ + Check if the Report relates to a SciPost-published object. + If it is, return a dict with info on relation to the published object, + based on Crossref's peer review content type. + """ + try: + publication = Publication.objects.get( + accepted_submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr) + except Publication.DoesNotExist: + return None + + relation = { + 'isReviewOfDOI': publication.doi_string, + 'stage': 'pre-publication', + 'type': 'referee-report', + 'title': 'Report on ' + self.submission.arxiv_identifier_w_vn_nr, + 'contributor_role': 'reviewer', + } + return relation + + @property + def citation(self): + citation = '' + if self.doi_string: + if self.anonymous: + citation += 'Anonymous, ' + else: + citation += '%s %s, ' % (self.author.user.first_name, self.author.user.last_name) + citation += 'Report on arXiv:%s, ' % self.submission.arxiv_identifier_w_vn_nr + citation += 'delivered %s, ' % self.date_submitted.strftime('%Y-%m-%d') + citation += 'doi: %s' % self.doi_string + return citation + + ########################## # EditorialCommunication # ########################## @@ -514,16 +585,18 @@ class EditorialCommunication(SubmissionRelatedObjectMixin, models.Model): Each individual communication between Editor-in-charge to and from Referees and Authors becomes an instance of this class. """ - submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, - related_name='editorial_communications') - referee = models.ForeignKey('scipost.Contributor', related_name='referee_in_correspondence', - blank=True, null=True, on_delete=models.CASCADE) + submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE) + referee = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE, + blank=True, null=True) comtype = models.CharField(max_length=4, choices=ED_COMM_CHOICES) timestamp = models.DateTimeField(default=timezone.now) text = models.TextField() + objects = EditorialCommunicationQueryset.as_manager() + class Meta: ordering = ['timestamp'] + default_related_name = 'editorial_communications' def __str__(self): output = self.comtype diff --git a/submissions/templates/partials/submissions/refereeing_status_card.html b/submissions/templates/partials/submissions/refereeing_status_card.html new file mode 100644 index 0000000000000000000000000000000000000000..1ab7c4136cf2b24e3c486d3f632873af9050f0cd --- /dev/null +++ b/submissions/templates/partials/submissions/refereeing_status_card.html @@ -0,0 +1,79 @@ + +<div class="card border-warning"> + <div class="card-body"> + {% if invitation.accepted is None %} + <h3 class="card-title">Referee Invitation response pending</h3> + <p class="card-text"> + In view of your expertise and on behalf of the Editor-in-charge we would like to invite you to referee this Submission. Please accept or decline this invitation. + We would be extremely grateful for your contribution, and thank you in advance for your consideration. + </p> + <a href="{% url 'submissions:accept_or_decline_ref_invitations' invitation.id %}" class="card-link">Accept or decline here</a> + {% elif invitation.accepted %} + <h3 class="card-title">Referee Invitation</h3> + <p class="card-text">Thank you for agreeing to referee this Submission. The following checklist will guide you through the steps needed to complete your refereeing task.</p> + <ul class="fa-ul"> + <li><i class="fa-li fa fa-check-square-o"></i>Accepted Invitation.</li> + + <li> + {% if invitation.fulfilled %} + <i class="fa-li fa fa-check-square-o"></i>Submitted Report on {{ invitation.related_report.date_submitted }}. + <ul class="list-style-none"> + <li>Status: <span class="{% if invitation.related_report.status == 'vetted' %}text-success{% elif invitation.related_report.status == 'unvetted' %}text-danger{% endif %}">{{ invitation.related_report.get_status_display }}</span></li> + <li>Anonymous: {{ invitation.related_report.anonymous|yesno:'Yes,No' }}</li> + {% if invitation.related_report.doi_label %}<li>DOI: {{ invitation.related_report.doi_string }}</li>{% endif %} + </ul> + {% else %} + <i class="fa-li fa fa-square-o"></i> + {% if invitation.related_report.is_in_draft %} + You have a Report in draft, <a href="{% url 'submissions:submit_report' invitation.submission.arxiv_identifier_w_vn_nr %}">finish your Report</a>. + {% else %} + <a href="{% url 'submissions:submit_report' invitation.submission.arxiv_identifier_w_vn_nr %}">Submit your Report</a>. + {% endif %} + {% endif %} + </li> + <li> + {% if invitation.related_report.is_vetted %} + <i class="fa-li fa fa-check-square-o"></i>Report vetted by Editor-in-charge. + {% else %} + <i class="fa-li fa fa-square-o"></i>Report vetted by Editor-in-charge. + {% endif %} + </li> + </ul> + + {% if invitation.related_report.anonymous %} + <p class="card-text">You have anonymously submitted your Report. <a href="{% url 'journals:sign_existing_report' report_id=invitation.related_report.id %}">You can click here to sign this Report</a> (leads to confirmation page).</p> + {% endif %} + + {% if invitation.submission.editor_in_charge %} + <h3 class="card-title">Communication</h3> + <a class="card-link" href="{% url 'submissions:communication' invitation.submission.arxiv_identifier_w_vn_nr 'RtoE' %}">Write to the Editor-in-charge</a> + + <ul class="pl-4 mt-2"> + {% for comm in communication %} + <li> + <span class="font-weight-bold"> + {% if comm.comtype == 'RtoE' %} + From {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} to Editor-in-charge + {% elif comm.comtype == 'EtoR' %} + From Editor-in-charge to + {% if comm.referee %} + {{ comm.referee.user.first_name }} {{ comm.referee.user.last_name }} + {% endif %} + {% endif %} + </span> + <small class="d-inline-block text-muted text-sm">on {{ comm.timestamp }}</small> + + <p class="card-text">{{ comm.text }}</p> + </li> + {% empty %} + <li>There have been no communications for this Submission.</li> + {% endfor %} + </ul> + {% endif %} + {% else %} + <h3 class="card-title">Referee Invitation</h3> + <p class="card-text">You have declined to contribute a Report. Nonetheless, we thank you very much for considering this refereeing invitation.</p> + <p class="card-text">Reason: {{ invitation.get_refusal_reason_display }}</p> + {% endif %} + </div> +</div> diff --git a/submissions/templates/submissions/_single_public_report_without_comments.html b/submissions/templates/submissions/_single_public_report_without_comments.html index 5f0a3cf451b00d72550a7e9da77a25270fbf617c..cd14902fb992c60cbd8637ef23a32ae738648149 100644 --- a/submissions/templates/submissions/_single_public_report_without_comments.html +++ b/submissions/templates/submissions/_single_public_report_without_comments.html @@ -7,18 +7,30 @@ {% if user.contributor == submission.editor_in_charge or user|is_in_group:'Editorial Administrators' and user|is_not_author_of_submission:submission.arxiv_identifier_w_vn_nr %} <div class="reportid"> - <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> + {% 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> + {% if report.doi_string or report.pdf_report %} + <ul class="clickables"> + {% if report.doi_string %} + <li>Cite as: <span class="citation">{{ report|citation }}</span></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> + {% if report.pdf_report %} + <li> + <a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank"><i class="fa fa-download"></i> Download as PDF</a> + </li> + {% endif %} + </ul> + {% endif %} + {% if perms.scipost.can_manage_reports %} + <h3 class="mt-2">Administration</h3> + <ul> + <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> + <li>Mark DOI as <a href="{% url 'journals:mark_report_doi_needed' report_id=report.id needed=1 %}">needed</a> / <a href="{% url 'journals:mark_report_doi_needed' report_id=report.id needed=0 %}">not needed</a></li> + <li><a href="{% url 'journals:generic_metadata_xml_deposit' type_of_object='report' object_id=report.id %}">Create the metadata and deposit it to Crossref</a></li> + </ul> + {% endif %} </div> {% if report.flagged %} @@ -49,18 +61,30 @@ </div> {% else %} <div class="reportid"> - <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 %} + <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> + {% if report.doi_string or report.pdf_report %} + <ul class="clickables"> + {% if report.doi_string %} + <li>Cite as: <span class="citation">{{ report|citation }}</span></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"><i class="fa fa-download"></i> Download as PDF</a> + </li> + {% endif %} + </ul> + {% endif %} + {% if perms.scipost.can_manage_reports %} + <h3 class="mt-2">Administration</h3> + <ul> + <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> + <li>Mark DOI as <a href="{% url 'journals:mark_report_doi_needed' report_id=report.id needed=1 %}">needed</a> / <a href="{% url 'journals:mark_report_doi_needed' report_id=report.id needed=0 %}">not needed</a></li> + <li><a href="{% url 'journals:generic_metadata_xml_deposit' type_of_object='report' object_id=report.id %}">Create the metadata and deposit it to Crossref</a></li> + </ul> + {% endif %} </div> {% include 'submissions/_single_report_content.html' with report=report %} diff --git a/submissions/templates/submissions/_single_report_ratings.html b/submissions/templates/submissions/_single_report_ratings.html index f5280e13d6be622a957562e602a698ea460647d4..56f04fc1bcde1fa93b098fdd873c68f4adf4c8af 100644 --- a/submissions/templates/submissions/_single_report_ratings.html +++ b/submissions/templates/submissions/_single_report_ratings.html @@ -1,4 +1,4 @@ -<div class="reportRatings mt-2"> +<div class="ratings"> <ul> <li>validity: {{report.get_validity_display}}</li> <li>significance: {{report.get_significance_display}}</li> diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html index a98239cdfab58ee3005ba7820c2c6c8ee2eb8b6d..dfd390661a321543e2c64ad961c8f6b529e7063c 100644 --- a/submissions/templates/submissions/submission_detail.html +++ b/submissions/templates/submissions/submission_detail.html @@ -10,10 +10,8 @@ <div class="container-outside breadcrumb-nav"> <div class="container"> <nav class="breadcrumb"> - - <a href="{% url 'submissions:submissions' %}" class="breadcrumb-item">Submissions</a> - <span class="breadcrumb-item">{{submission.arxiv_identifier_w_vn_nr}}</span> - + <a href="{% url 'submissions:submissions' %}" class="breadcrumb-item">Submissions</a> + <span class="breadcrumb-item">{{submission.arxiv_identifier_w_vn_nr}}</span> </nav> </div> </div> @@ -22,7 +20,7 @@ {% block content %} <div class="row"> - <div class="col-12"> + <div class="col"> <h2>SciPost Submission Page</h2> <h1 class="text-primary">{{submission.title}}</h1> <h3 class="mb-3">by {{submission.author_list}}</h3> @@ -59,11 +57,6 @@ {% endif %} </div> - </div> -</div> - -<div class="row"> - <div class="col-12"> <h3>Submission summary</h3> {% include 'submissions/_submission_summary.html' with submission=submission hide_title=1 %} @@ -83,6 +76,14 @@ <div class="blockquote">{{ submission.list_of_changes|linebreaks }}</div> {% endif %} </div> + + {% if invitations %} + <div class="col-md-4"> + {% for invitation in invitations %} + {% include 'partials/submissions/refereeing_status_card.html' with invitation=invitation %} + {% endfor %} + </div> + {% endif %} </div> {% if is_author or user|is_in_group:'Editorial College' or user|is_in_group:'Editorial Administrators' %} @@ -170,8 +171,10 @@ {% endif %} {% if invited_reports %} -{# <hr>#} -<div class="row mt-4"> + +<hr class="divider"> + +<div class="row"> <div class="col-12"> <div class="card card-grey"> <div class="card-body"> @@ -191,8 +194,9 @@ {% endif %} {% if contributed_reports %} -{# <hr>#} -<div class="row mt-4"> +<hr class="divider"> + +<div class="row"> <div class="col-12"> <div class="card card-grey"> <div class="card-body"> @@ -219,7 +223,10 @@ {% endif %} {% endif %} -{% include 'scipost/comments_block.html' with comments=submission.comments.vetted %} +{% if submission.comments.vetted %} + <hr class="divider"> + {% include 'scipost/comments_block.html' with comments=submission.comments.vetted %} +{% endif %} {# This is an apparent redundant logic block; however, it makes sure the "login to ..." links wouldn't be shown twice! #} diff --git a/submissions/templatetags/submissions_extras.py b/submissions/templatetags/submissions_extras.py index 97943119c4c443baf69fdaf9b1a477d53a550475..f63b5843f7d9be03df5dda65ef157acd102588cd 100644 --- a/submissions/templatetags/submissions_extras.py +++ b/submissions/templatetags/submissions_extras.py @@ -24,9 +24,18 @@ def is_viewable_by_authors(recommendation): @register.filter def user_is_referee(submission, user): + if not user.is_authenticated: + return False return submission.referee_invitations.filter(referee__user=user).exists() @register.filter def is_voting_fellow(submission, user): + if not user.is_authenticated: + return False return submission.voting_fellows.filter(contributor__user=user).exists() + + +@register.filter +def citation(citable): + return citable.citation diff --git a/submissions/views.py b/submissions/views.py index 0ca51573eba2f46c64fe20bc7eb903a8b725437e..21a0dbbe5e99f518a3805c3b5a41171538285151 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -211,6 +211,12 @@ def submission_detail(request, arxiv_identifier_w_vn_nr): author_replies = (submission.comments.vetted() .filter(is_author_reply=True).order_by('-date_submitted')) + # User is referee for the Submission + invitations = submission.referee_invitations.filter(referee__user=request.user) + if invitations: + context['communication'] = submission.editorial_communications.for_referees().filter( + referee__user=request.user) + recommendations = submission.eicrecommendations.all() context.update({ @@ -224,6 +230,7 @@ def submission_detail(request, arxiv_identifier_w_vn_nr): 'form': form, 'is_author': is_author, 'is_author_unchecked': is_author_unchecked, + 'invitations': invitations, }) return render(request, 'submissions/submission_detail.html', context) @@ -890,8 +897,7 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): RefereeInvitations need to be either accepted or declined by the invited user using this view. The decision will be taken one invitation at a time. """ - invitation = RefereeInvitation.objects.filter( - referee__user=request.user, accepted=None, cancelled=False) + invitation = RefereeInvitation.objects.awaiting_response().filter(referee__user=request.user) if invitation_id: try: invitation = invitation.get(id=invitation_id) @@ -919,7 +925,7 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): invitation.accepted = False decision_string = 'declined' invitation.refusal_reason = form.cleaned_data['refusal_reason'] - messages.success(request, ('<h1>You have declined to contribute a Report</h1>' + messages.success(request, ('<h3>You have declined to contribute a Report</h3>' 'Nonetheless, we thank you very much for considering' ' this refereeing invitation.</p>')) invitation.save() @@ -933,7 +939,10 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): invitation.submission.add_event_for_eic('Referee %s has %s the refereeing invitation.' % (invitation.referee.user.last_name, decision_string)) - return redirect('submissions:accept_or_decline_ref_invitations') + + if request.user.contributor.referee_invitations.awaiting_response().exists(): + return redirect('submissions:accept_or_decline_ref_invitations') + return redirect(invitation.submission.get_absolute_url()) form = ConsiderRefereeInvitationForm() context = { 'invitation': invitation, @@ -1095,6 +1104,7 @@ 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. """ + referee = None if comtype == 'AtoE': submissions_qs = Submission.objects.filter(authors__user=request.user) else: @@ -1131,14 +1141,19 @@ def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): if referee_id is not None: referee = get_object_or_404(Contributor, pk=referee_id) communication.referee = referee + + if comtype == 'RtoE': + communication.referee = request.user.contributor communication.save() SubmissionUtils.load({'communication': communication}) SubmissionUtils.send_communication_email() if comtype == 'EtoA' or comtype == 'EtoR' or comtype == 'EtoS': return redirect(reverse('submissions:editorial_page', kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) - elif comtype == 'AtoE' or comtype == 'RtoE': + elif comtype == 'AtoE': return redirect(reverse('scipost:personal_page')) + elif comtype == 'RtoE': + return redirect(submission.get_absolute_url()) elif comtype == 'StoE': return redirect(reverse('submissions:pool')) @@ -1306,7 +1321,7 @@ def submit_report(request, arxiv_identifier_w_vn_nr): % request.user.last_name) messages.success(request, 'Thank you for your Report') - return redirect(reverse('scipost:personal_page')) + return redirect(submission.get_absolute_url()) context = {'submission': submission, 'form': form} return render(request, 'submissions/submit_report.html', context) diff --git a/theses/templates/theses/thesis_detail.html b/theses/templates/theses/thesis_detail.html index 7ed53d775a8bdfde69e842e8803cd6b4d6ec91a9..46df60782bdd374301843c0145bdabdaa51799af 100644 --- a/theses/templates/theses/thesis_detail.html +++ b/theses/templates/theses/thesis_detail.html @@ -14,7 +14,10 @@ </div> </div> -{% include 'scipost/comments_block.html' with comments=thesislink.comments.vetted type_of_object='ThesisLink' %} +{% if thesislink.comments.vetted %} + <hr class="divider"> + {% include 'scipost/comments_block.html' with comments=thesislink.comments.vetted type_of_object='ThesisLink' %} +{% endif %} {% include 'comments/new_comment.html' with object_id=thesislink.id type_of_object='thesislink' open_for_commenting=thesislink.open_for_commenting %} diff --git a/theses/templates/theses/thesislink_list.html b/theses/templates/theses/thesislink_list.html index 0e417c3656c7a5f784afd6f3172d5f58c014efc2..366df71def6d21942c125873c06967d3493d055d 100644 --- a/theses/templates/theses/thesislink_list.html +++ b/theses/templates/theses/thesislink_list.html @@ -6,7 +6,7 @@ {% block pagetitle %}: Theses{% endblock pagetitle %} {% block headsup %} -<script type="text/javascript" async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML"></script> + <script type="text/javascript" async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML"></script> {% endblock headsup %} {% block content %} diff --git a/virtualmeetings/templates/virtualmeetings/VGM_detail.html b/virtualmeetings/templates/virtualmeetings/VGM_detail.html index 399a7881308467630fae1f63944cc873828d5df8..230b9b4e8207bd86b227390e961b0bec461fcd4b 100644 --- a/virtualmeetings/templates/virtualmeetings/VGM_detail.html +++ b/virtualmeetings/templates/virtualmeetings/VGM_detail.html @@ -151,67 +151,88 @@ </div> </div> -{% if nominations %} - <div class="row"> - <div class="col-12"> - <h2 class="highlight">Nominations under consideration ({{nominations|length}})</h2> - </div> +<div class="row"> + <div class="col-12"> + <h2 class="highlight">Nominations under consideration ({{nominations|length}})</h2> </div> - <div class="row"> - <div class="col-12"> - <ul class="list-group list-group-flush"> - {% for nomination in nominations %} - <li class="list-group-item border-0"> - <div class="card-body"> - {% include 'virtualmeetings/nomination_content.html' with nomination=nomination %} - <br/> - <div class="opinionsDisplay mb-3"> - <h4>Your opinion on this Nomination (voting deadline: {{ nomination.voting_deadline|date:'y-m-d' }}):</h4> - <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='A' %}" method="post"> - {% csrf_token %} - <input type="submit" class="agree" value="Agree {{ nomination.nr_A }} "/> - </form> - <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='N' %}" method="post"> - {% csrf_token %} - <input type="submit" class="notsure" value="Not sure {{ nomination.nr_N }}"/> - </form> - <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='D'%}" method="post"> - {% csrf_token %} - <input type="submit" class="disagree" value="Disagree {{ nomination.nr_D }}"/> - </form> - {% if request.user.contributor in nomination.in_agreement.all %} - <strong>(you have voted: Agreed)</strong> - {% elif request.user.contributor in nomination.in_notsure.all %} - <strong>(you have voted: Not sure)</strong> - {% elif request.user.contributor in nomination.in_disagreement.all %} - <strong>(you have voted: Disagree)</strong> - {% endif %} - </div> - <br> - <a href="javascript:;" class="btn btn-secondary" data-toggle="toggle" data-target="#remarkForm{{ nomination.id }}">Add a remark on this Nomination</a> - <div class="submitRemarkForm mt-3 mb-4" id="remarkForm{{ nomination.id }}" style="display: none;"> - <form action="{% url 'virtualmeetings:add_remark_on_nomination' VGM_id=VGM.id nomination_id=nomination.id %}" method="post"> - {% csrf_token %} - {{ remark_form|bootstrap:'0,12' }} - <input type="submit" class="btn btn-secondary" value="Submit" /> - </form> +</div> +<div class="row"> + <div class="col-12" id="accordion"> + {% for domain, spec in spec_list %} + <div class="card"> + <div class="card-body"> + <a href="#" class="card-link" data-toggle="collapse" data-target="#collapse{{ domain|cut:" " }}" aria-expanded="false" aria-controls="collapse{{ domain|cut:" " }}">{{ domain }}</a> + </div> + <!-- Domain --> + <div class="card-body collapse bg-white" id="collapse{{ domain|cut:" " }}" aria-labelledby="heading{{ domain|cut:" " }}" data-parent="#accordion"> + {% for sp, val in spec %} + <div class="card"> + <div class="card-body bg-white"> + <a href="#" class="card-link" id="heading{{ forloop.counter }}" data-toggle="collapse" data-target="#collapse{{ forloop.counter }}" aria-expanded="false" aria-controls="collapse{{ forloop.counter }}">{{ sp }}</a> + <br>{{ val }} </div> - {% if nomination.remarks.all %} - <h3>Remarks on this nomination:</h3> - <ul> - {% for rem in nomination.remarks.all %} - {% include 'scipost/_remark_li.html' with remark=rem %} - {% endfor %} - </ul> - {% endif %} + <ul class="list-group list-group-flush collapse" id="collapse{{ forloop.counter }}" aria-labelledby="heading{{ forloop.counter }}" data-parent="#collapse{{ domain|cut:" " }}"> + {% for nomination in nominations %} + {% if sp in nomination.expertises %} + <li class="list-group-item"> + <div class="card-body bg-white"> + {% include 'virtualmeetings/nomination_content.html' with nomination=nomination %} + </div> + <div class="card-body bg-white"> + <div class="opinionsDisplay mx-0 px-3 py-2"> + <h4>Your opinion on this Nomination (voting deadline: {{ nomination.voting_deadline|date:'y-m-d' }}):</h4> + <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='A' %}" method="post"> + {% csrf_token %} + <input type="submit" class="agree" value="Agree {{ nomination.nr_A }} "/> + </form> + <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='N' %}" method="post"> + {% csrf_token %} + <input type="submit" class="notsure" value="Not sure {{ nomination.nr_N }}"/> + </form> + <form action="{% url 'virtualmeetings:vote_on_nomination' nomination_id=nomination.id vote='D'%}" method="post"> + {% csrf_token %} + <input type="submit" class="disagree" value="Disagree {{ nomination.nr_D }}"/> + </form> + {% if request.user.contributor in nomination.in_agreement.all %} + <strong>(you have voted: Agreed)</strong> + {% elif request.user.contributor in nomination.in_notsure.all %} + <strong>(you have voted: Not sure)</strong> + {% elif request.user.contributor in nomination.in_disagreement.all %} + <strong>(you have voted: Disagree)</strong> + {% endif %} + </div> + </div> + <div class="card-body bg-white"> + <a href="javascript:;" class="card-link btn btn-secondary" data-toggle="toggle" data-target="#remarkForm{{ nomination.id }}">Add a remark on this Nomination</a> + <div class="submitRemarkForm my-3" id="remarkForm{{ nomination.id }}" style="display: none;"> + <form action="{% url 'virtualmeetings:add_remark_on_nomination' VGM_id=VGM.id nomination_id=nomination.id %}" method="post"> + {% csrf_token %} + {{ remark_form|bootstrap:'0,12' }} + <input type="submit" class="btn btn-secondary" value="Submit" /> + </form> + </div> + </div> + <div class="card-body bg-white"> + <h3>Remarks on this nomination</h3> + <ul> + {% for rem in nomination.remarks.all %} + {% include 'scipost/_remark_li.html' with remark=rem %} + {% empty %} + <li><em>No Remarks found</em></li> + {% endfor %} + </ul> + </div> + </li> + {% endif %} + {% endfor %} + </ul> </div> - </li> - <hr> - {% endfor %} - </ul> - </div> + {% endfor %} + </div><!-- End Domain --> + </div> + {% endfor %} </div> -{% endif %} +</div> <!-- Motions --> @@ -239,60 +260,60 @@ </div> </div> -{% for key, val in motion_categories_dict.items %} - <div class="row"> - <div class="col-12"><h2>{{ val }}:</h2></div> - <div class="col-md-11 ml-auto"> - <ul> - {% for motion in VGM.motion_set.all %} - {% if motion.category == key %} - <li> - {% include 'virtualmeetings/motion_content.html' with motion=motion %} - <div class="d-block mb-3 opinionsDisplay"> - <h4>Your opinion on this Motion (voting deadline: {{ motion.voting_deadline|date:'y-m-d' }}):</h4> - <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='A' %}" method="post"> - {% csrf_token %} - <input type="submit" class="agree" value="Agree {{ motion.nr_A }} "/> - </form> - <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='N' %}" method="post"> - {% csrf_token %} - <input type="submit" class="notsure" value="Not sure {{ motion.nr_N }}"/> - </form> - <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='D'%}" method="post"> - {% csrf_token %} - <input type="submit" class="disagree" value="Disagree {{ motion.nr_D }}"/> - </form> - {% if request.user.contributor in motion.in_agreement.all %} - <strong>(you have voted: Agreed)</strong> - {% elif request.user.contributor in motion.in_notsure.all %} - <strong>(you have voted: Not sure)</strong> - {% elif request.user.contributor in motion.in_disagreement.all %} - <strong>(you have voted: Disagree)</strong> + {% for key, val in motion_categories_dict.items %} + <div class="row"> + <div class="col-12"><h2>{{ val }}:</h2></div> + <div class="col-md-11 ml-auto"> + <ul> + {% for motion in VGM.motion_set.all %} + {% if motion.category == key %} + <li> + {% include 'virtualmeetings/motion_content.html' with motion=motion %} + <div class="d-block mb-3 opinionsDisplay"> + <h4>Your opinion on this Motion (voting deadline: {{ motion.voting_deadline|date:'y-m-d' }}):</h4> + <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='A' %}" method="post"> + {% csrf_token %} + <input type="submit" class="agree" value="Agree {{ motion.nr_A }} "/> + </form> + <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='N' %}" method="post"> + {% csrf_token %} + <input type="submit" class="notsure" value="Not sure {{ motion.nr_N }}"/> + </form> + <form action="{% url 'virtualmeetings:vote_on_motion' motion_id=motion.id vote='D'%}" method="post"> + {% csrf_token %} + <input type="submit" class="disagree" value="Disagree {{ motion.nr_D }}"/> + </form> + {% if request.user.contributor in motion.in_agreement.all %} + <strong>(you have voted: Agreed)</strong> + {% elif request.user.contributor in motion.in_notsure.all %} + <strong>(you have voted: Not sure)</strong> + {% elif request.user.contributor in motion.in_disagreement.all %} + <strong>(you have voted: Disagree)</strong> + {% endif %} + </div> + <a class="btn btn-secondary" href="javascript:;" data-toggle="toggle" data-target="#remarkForm{{ motion.id }}">Add a remark on this Motion</a> + <div class="submitRemarkForm mt-3" id="remarkForm{{ motion.id }}" style="display: none;"> + <form action="{% url 'virtualmeetings:add_remark_on_motion' motion_id=motion.id %}" method="post"> + {% csrf_token %} + {{ remark_form|bootstrap:"0,12" }} + <input type="submit" class="btn btn-secondary" value="Submit" /> + </form> + </div> + {% if motion.remarks.all %} + <h3>Remarks on this motion:</h3> + <ul> + {% for rem in motion.remarks.all %} + {% include 'scipost/_remark_li.html' with remark=rem %} + {% endfor %} + </ul> {% endif %} - </div> - <a class="btn btn-secondary" href="javascript:;" data-toggle="toggle" data-target="#remarkForm{{ motion.id }}">Add a remark on this Motion</a> - <div class="submitRemarkForm mt-3" id="remarkForm{{ motion.id }}" style="display: none;"> - <form action="{% url 'virtualmeetings:add_remark_on_motion' motion_id=motion.id %}" method="post"> - {% csrf_token %} - {{ remark_form|bootstrap:"0,12" }} - <input type="submit" class="btn btn-secondary" value="Submit" /> - </form> - </div> - {% if motion.remarks.all %} - <h3>Remarks on this motion:</h3> - <ul> - {% for rem in motion.remarks.all %} - {% include 'scipost/_remark_li.html' with remark=rem %} - {% endfor %} - </ul> - {% endif %} - <hr> - </li> - {% endif %} - {% endfor %} - </ul> - </div> - </div> + <hr> + </li> + {% endif %} + {% endfor %} + </ul> + </div> + </div> {% endfor %} {% endblock %} diff --git a/virtualmeetings/templates/virtualmeetings/motion_content.html b/virtualmeetings/templates/virtualmeetings/motion_content.html index d809e9a219d09c7af732c14e4edefe64bee9f379..dcc7acc48f9527db37fd68b4701059743bd5769c 100644 --- a/virtualmeetings/templates/virtualmeetings/motion_content.html +++ b/virtualmeetings/templates/virtualmeetings/motion_content.html @@ -1,6 +1,6 @@ <div class="Motion" id="motion_{{ motion.id }}"> <h2 class="pb-0">Motion {{ motion.id }}</h2> - <h3 class="pt-0 mb-2">put forward by {{ motion.put_forward_by.user.first_name }} {{ motion.put_forward_by.user.first_name }}</h3> + <h3 class="pt-0 mb-2">put forward on {{ motion.date|date:"Y-m-d" }} by {{ motion.put_forward_by.user.first_name }} {{ motion.put_forward_by.user.last_name }}</h3> <h3>Background:</h3> <div>{{ motion.background|linebreaks }}</div> diff --git a/virtualmeetings/views.py b/virtualmeetings/views.py index cb3d7984b9d226a453a2a43fdd4e91df6ea40057..d12759c0f27c7cddf47ccfc94a64271d3ca5ba9e 100644 --- a/virtualmeetings/views.py +++ b/virtualmeetings/views.py @@ -11,6 +11,7 @@ from .constants import motion_categories_dict from .forms import FeedbackForm, NominationForm, MotionForm from .models import VGM, Feedback, Nomination, Motion +from scipost.constants import SCIPOST_SUBJECT_AREAS from scipost.forms import RemarkForm from scipost.models import RegistrationInvitation, Contributor, Remark @@ -35,8 +36,9 @@ def VGM_detail(request, VGM_id): pending_inv_Fellows = RegistrationInvitation.objects.pending_invited_fellows() declined_inv_Fellows = RegistrationInvitation.objects.declined_invited_fellows() + spec_list = SCIPOST_SUBJECT_AREAS # subject_areas_dict nomination_form = NominationForm() - nominations = Nomination.objects.filter(accepted=None).order_by('last_name') + nominations = Nomination.objects.filter(VGM=VGM_instance, accepted=None).order_by('last_name') motion_form = MotionForm() remark_form = RemarkForm() context = { @@ -47,6 +49,7 @@ def VGM_detail(request, VGM_id): 'current_Fellows': current_Fellows, 'pending_inv_Fellows': pending_inv_Fellows, 'declined_inv_Fellows': declined_inv_Fellows, + 'spec_list': spec_list, 'nominations': nominations, 'nomination_form': nomination_form, 'motion_categories_dict': motion_categories_dict, @@ -107,22 +110,15 @@ def nominate_Fellow(request, VGM_id): nomination_form = NominationForm(request.POST) if nomination_form.is_valid(): - nomination = Nomination( - VGM=VGM_instance, - by=request.user.contributor, - date=timezone.now().date(), - first_name=nomination_form.cleaned_data['first_name'], - last_name=nomination_form.cleaned_data['last_name'], - discipline=nomination_form.cleaned_data['discipline'], - expertises=nomination_form.cleaned_data['expertises'], - webpage=nomination_form.cleaned_data['webpage'], - voting_deadline=VGM_instance.end_date + datetime.timedelta(days=7), - ) + nomination = nomination_form.save(commit=False) + nomination.VGM = VGM_instance + nomination.by = request.user.contributor + nomination.voting_deadline = VGM_instance.end_date + datetime.timedelta(days=7) nomination.save() nomination.update_votes(request.user.contributor.id, 'A') messages.success(request, 'The nomination has been registered.') else: - messages.danger(request, 'The form was not filled properly.') + messages.warning(request, 'The form was not filled properly.') return redirect(VGM_instance.get_absolute_url()) diff --git a/webpack.config.js b/webpack.config.js index b27be106e76544fa453dadb207f296cebe238ad2..6a9275d4de51bfd576ea29122e1eb64da64ec829 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,6 +10,7 @@ module.exports = { entry: { main: [ "bootstrap-loader", + "./scipost/static/scipost/assets/js/dynamic_loading.js", "./scipost/static/scipost/assets/js/scripts.js", ], homepage: [