diff --git a/journals/forms.py b/journals/forms.py index 4532ce78c841b1c276ea41570e5b769656e6b735..daa7220d2182f15254df293cddbcd6cf33b53e43 100644 --- a/journals/forms.py +++ b/journals/forms.py @@ -2,7 +2,7 @@ from django import forms from django.utils import timezone from .models import SCIPOST_JOURNALS -from .models import Issue, Publication +from .models import UnregisteredAuthor, Issue, Publication from submissions.models import Submission @@ -86,6 +86,12 @@ class ValidatePublicationForm(forms.ModelForm): 'latest_activity',] +class UnregisteredAuthorForm(forms.ModelForm): + class Meta: + model = UnregisteredAuthor + fields = ['first_name', 'last_name'] + + class CitationListBibitemsForm(forms.Form): latex_bibitems = forms.CharField(widget=forms.Textarea()) diff --git a/journals/models.py b/journals/models.py index d7f8d7eb8958b3840f834fcf1adae83a25995ff4..08421e40dca860d307edabf8fa70142efd2e8577 100644 --- a/journals/models.py +++ b/journals/models.py @@ -7,6 +7,14 @@ from scipost.models import SCIPOST_DISCIPLINES, SCIPOST_SUBJECT_AREAS, subject_a from scipost.models import ChoiceArrayField, Contributor +class UnregisteredAuthor(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + + def __str__(self): + return self.first_name + ' ' + self.last_name + + SCIPOST_JOURNALS = ( ('SciPost Physics Select', 'SciPost Physics Select'), ('SciPost Physics', 'SciPost Physics'), @@ -158,6 +166,7 @@ class Publication(models.Model): author_list = models.CharField(max_length=1000, verbose_name="author list") # Authors which have been mapped to contributors: authors = models.ManyToManyField (Contributor, blank=True, related_name='authors_pub') + authors_unregistered = models.ManyToManyField (UnregisteredAuthor, blank=True) first_author = models.ForeignKey (Contributor, blank=True, null=True) authors_claims = models.ManyToManyField (Contributor, blank=True, related_name='authors_pub_claims') diff --git a/journals/templates/journals/add_author.html b/journals/templates/journals/add_author.html new file mode 100644 index 0000000000000000000000000000000000000000..15aef547274bd2fa6a9bd9764b42ffe7b2c9561c --- /dev/null +++ b/journals/templates/journals/add_author.html @@ -0,0 +1,85 @@ +{% extends 'scipost/base.html' %} + +{% block pagetitle %}: add author to publication{% endblock pagetitle %} + +{% block headsup %} + +{% load scipost_extras %} + +{% endblock headsup %} + +{% block bodysup %} + + +<section> + <div class="flex-greybox"> + <h1>Add author to publication</h1> + </div> + {{ publication.details }} +</section> + + +<section> + <div class="flex-greybox"> + <h1>Add an (unregistered) author</h1> + </div> + + <h3>Current list of authors as contributors:</h3> + <p> + {% for author in publication.authors.all %} + <a href="/contributor/{{ author.id }}">{{ author.user.first_name }} {{ author.user.last_name }}</a> + {% endfor %} + </p> + <h3>Current list of additional authors (unregistered):</h3> + <p> + {% for author in publication.authors_unregistered.all %} + {{ author }} + {% endfor %} + </p> + + <h3>Search for missing author:</h3> + <form action="{% url 'journals:add_author' publication_id=publication.id %}" method="post"> + {% csrf_token %} + {{ form.as_p }} + <input type="submit" value="Search"> + </form> + + {% if contributors_found %} + <h3>Identified as contributor:</h3> + <table> + {% for contributor in contributors_found %} + <tr><td>{{ contributor.user.first_name }} {{ contributor.user.last_name }}</td><td> </td> + <td><a href="{% url 'journals:add_author' publication_id=publication.id contributor_id=contributor.id %}">Add this Contributor as author of this Publication</a></td></tr> + {% endfor %} + </table> + {% elif form.has_changed %} + <p>No Contributor with this name could be identified.</p> + {% endif %} + <br/> + + {% if unregistered_authors_found %} + <h3>Identified as existing unregistered author:</h3> + <table> + {% for unreg_auth in unregistered_authors_found %} + <tr><td>{{ unreg_auth }}</td><td> </td> + <td><a href="{% url 'journals:add_author' publication_id=publication.id unregistered_author_id=unreg_auth.id %}">Add this unregistered author as author of this Publication</a></td></tr> + {% endfor %} + </table> + {% elif form.has_changed %} + <p>No UnregisteredAuthor with this name could be found in the database.</p> + {% endif %} + <br/> + + <h3>You can otherwise create an UnregisteredAuthor object instance and link it to this publication:</h3> + <form action="{% url 'journals:add_new_unreg_author' publication_id=publication.id %}" method="post"> + {% csrf_token %} + {{ new_unreg_author_form.as_p }} + <input type="submit" value="Add"> + </form> + + <h3><a href="{% url 'scipost:publication_detail' doi_string=publication.doi_string %}">Return to the publication's page</a></h3> + +</section> + + +{% endblock bodysup %} diff --git a/journals/templates/journals/publication_detail.html b/journals/templates/journals/publication_detail.html index bf4f819ba173182cda504cf3d2365a406054786b..4d1c16b8a508ba1201184727ff14cb6afca32850 100644 --- a/journals/templates/journals/publication_detail.html +++ b/journals/templates/journals/publication_detail.html @@ -23,16 +23,27 @@ <h3>View more material from these authors:</h3> <p> {% for author in publication.authors.all %} - <a href="/contributor/{{ author.id }}">{{ author.user.first_name }} {{ author.user.last_name }}</a> + <a href="/contributor/{{ author.id }}">{{ author }}</a> + {% endfor %} + {% for author in publication.authors_unregistered.all %} + {{ author }} {% endfor %} </p> {% if request.user|is_in_group:'Editorial Administrators' %} <hr class="hr12"/> - <h3>Editorial Administration: Metadata creation and registration</h3> + <h3>Editorial Administration tools: </h3> <ul> - <li><a href="{% url 'journals:create_citation_list_metadata' doi_string=publication.doi_string%}">Create/update citation list metadata</a></li> - <li><a href="{% url 'journals:create_funding_info_metadata' doi_string=publication.doi_string%}">Create/update funding info metadata</a></li> + <li>Mark the first author (currently: {{ publication.first_author }}) + <ul> + {% for author in publication.authors.all %} + <li><a href="{% url 'journals:mark_first_author' publication_id=publication.id contributor_id=author.id %}">{{ author }}</a></li> + {% endfor %} + </ul> + </li> + <li><a href="{% url 'journals:add_author' publication_id=publication.id %}">Add a missing author</a></li> + <li><a href="{% url 'journals:create_citation_list_metadata' doi_string=publication.doi_string %}">Create/update citation list metadata</a></li> + <li><a href="{% url 'journals:create_funding_info_metadata' doi_string=publication.doi_string %}">Create/update funding info metadata</a></li> <li><a href="{% url 'journals:create_metadata_xml' doi_string=publication.doi_string %}">Create/update the XML metadata</a></li> <li><a href="{% url 'journals:metadata_xml_deposit' doi_string=publication.doi_string option='test' %}">Test metadata deposit (via Crossref test server)</a></li> <li><a href="{% url 'journals:metadata_xml_deposit' doi_string=publication.doi_string option='deposit' %}">Deposit the metadata to Crossref</a></li> diff --git a/journals/urls.py b/journals/urls.py index 6afabd6ddfb0561f32b8ade169efc34b2df0445a..38d2ad6cc4681f74e856155269a8a71caacf86a2 100644 --- a/journals/urls.py +++ b/journals/urls.py @@ -43,6 +43,15 @@ urlpatterns = [ 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'^add_author/(?P<publication_id>[0-9]+)$', + journals_views.add_author, + name='add_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'^create_citation_list_metadata/(?P<publication_id>[0-9]+)$', url(r'^create_citation_list_metadata/(?P<doi_string>10.21468/[a-zA-Z]+.[0-9]+.[0-9]+.[0-9]{3,})$', journals_views.create_citation_list_metadata, diff --git a/journals/views.py b/journals/views.py index 7e238ee81555c5d323b6c8e001e61c1d55b943df..35c7a1a5b38f341949134a68bfcc0c14a1f022be 100644 --- a/journals/views.py +++ b/journals/views.py @@ -317,6 +317,80 @@ def validate_publication(request): return render(request, 'journals/validate_publication.html', context) +@permission_required('scipost.can_publish_accepted_submission', return_403=True) +@transaction.atomic +def mark_first_author(request, publication_id, contributor_id): + publication = get_object_or_404(Publication, id=publication_id) + contributor = get_object_or_404(Contributor, id=contributor_id) + publication.first_author = contributor + publication.save() + return redirect(reverse('scipost:publication_detail', + kwargs={'doi_string': publication.doi_string,})) + + +@permission_required('scipost.can_publish_accepted_submission', return_403=True) +@transaction.atomic +def add_author(request, publication_id, contributor_id=None, unregistered_author_id=None): + """ + If not all authors are registered Contributors or if they have not + all claimed authorship, this method allows editorial administrators + to associated them to the publication. + This is important for the Crossref metadata, in which all authors must appear. + """ + publication = get_object_or_404(Publication, id=publication_id) + if contributor_id: + contributor = get_object_or_404(Contributor, id=contributor_id) + publication.authors.add(contributor) + publication.save() + return redirect(reverse('scipost:publication_detail', + kwargs={'doi_string': publication.doi_string,})) + elif unregistered_author_id: + unregistered_author = get_object_or_404(UnregisteredAuthor, id=unregistered_author_id) + publication.unregistered_authors.add(unregistered_author) + publication.save() + return redirect(reverse('scipost:publication_detail', + kwargs={'doi_string': publication.doi_string,})) + if request.method == 'POST': + form = UnregisteredAuthorForm(request.POST) + if form.is_valid(): + contributors_found = Contributor.objects.filter( + user__last_name__icontains=form.cleaned_data['last_name']) + unregistered_authors_found = UnregisteredAuthor.objects.filter( + last_name__icontains=form.cleaned_data['last_name']) + new_unreg_author_form = UnregisteredAuthorForm( + initial={'first_name': form.cleaned_data['first_name'], + 'last_name': form.cleaned_data['last_name'],}) + else: + form = UnregisteredAuthorForm() + contributors_found = None + unregistered_authors_found = None + new_unreg_author_form = UnregisteredAuthorForm() + context = {'publication': publication, + 'contributors_found': contributors_found, + 'unregistered_authors_found': unregistered_authors_found, + 'form': form, + 'new_unreg_author_form': new_unreg_author_form,} + return render(request, 'journals/add_author.html', context) + + +@permission_required('scipost.can_publish_accepted_submission', return_403=True) +@transaction.atomic +def add_new_unreg_author(request, publication_id): + publication = get_object_or_404(Publication, id=publication_id) + if request.method == 'POST': + new_unreg_author_form = UnregisteredAuthorForm(request.POST) + if new_unreg_author_form.is_valid(): + new_unreg_author = UnregisteredAuthor( + first_name = new_unreg_author_form.cleaned_data['first_name'], + last_name = new_unreg_author_form.cleaned_data['last_name'],) + new_unreg_author.save() + publication.authors_unregistered.add(new_unreg_author) + return redirect(reverse('scipost:publication_detail', + kwargs={'doi_string': publication.doi_string,})) + errormessage = 'Method add_new_unreg_author can only be called with POST.' + return render(request, 'scipost/error.html', context={'errormessage': errormessage}) + + @permission_required('scipost.can_publish_accepted_submission', return_403=True) @transaction.atomic def create_citation_list_metadata(request, doi_string): @@ -471,6 +545,15 @@ def create_metadata_xml(request, doi_string): initial['metadata_xml'] += '<ORCID>http://orcid.org/' + author.orcid_id + '</ORCID>' initial['metadata_xml'] += '</person_name>\n' + for author_unreg in publication.authors_unregistered.all(): + #publication.metadata_xml += ( + initial['metadata_xml'] += ( + '<person_name sequence=\'additional\' contributor_role=\'author\'> ' + '<given_name>' + author_unreg.first_name + '</given_name> ' + '<surname>' + author_unreg.last_name + '</surname> ' + '</person_name>' + ) + #publication.metadata_xml += '</contributors>\n' initial['metadata_xml'] += '</contributors>\n'