From 8da607b713b34b28b39f286a1132b8d760465cc8 Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Mon, 5 Aug 2024 17:33:10 +0200 Subject: [PATCH] add supplemental information publication resources fixes #316 --- scipost_django/journals/forms.py | 16 ++++ scipost_django/journals/managers.py | 3 + .../0135_alter_publicationresource__type.py | 25 ++++++ scipost_django/journals/models/resource.py | 2 + .../manage_publication_resources.html | 8 +- .../journals/publication_detail.html | 78 ++++++++++++------- scipost_django/journals/urls/general.py | 5 ++ scipost_django/journals/views.py | 48 ++++++++++++ 8 files changed, 153 insertions(+), 32 deletions(-) create mode 100644 scipost_django/journals/migrations/0135_alter_publicationresource__type.py diff --git a/scipost_django/journals/forms.py b/scipost_django/journals/forms.py index 4c22f8114..c956f800e 100644 --- a/scipost_django/journals/forms.py +++ b/scipost_django/journals/forms.py @@ -693,6 +693,22 @@ class DraftPublicationForm(forms.ModelForm): ) self.instance.topics.add(*self.submission.topics.all()) + # Create supplementary information for any provided external links + if self.submission.code_repository_url: + PublicationResource.objects.get_or_create( + publication=self.instance, + _type=PublicationResource.TYPE_SUP_INFO, + url=self.submission.code_repository_url, + comments="Code repository", + ) + if self.submission.data_repository_url: + PublicationResource.objects.get_or_create( + publication=self.instance, + _type=PublicationResource.TYPE_SUP_INFO, + url=self.submission.data_repository_url, + comments="Data repository", + ) + def prefill_fields(self): if self.submission: self.fields["title"].initial = self.submission.title diff --git a/scipost_django/journals/managers.py b/scipost_django/journals/managers.py index c2bce4fdc..4d73e6848 100644 --- a/scipost_django/journals/managers.py +++ b/scipost_django/journals/managers.py @@ -96,3 +96,6 @@ class PublicationResourceQuerySet(models.QuerySet): def live(self): return self.filter(_type=self.model.TYPE_LIVE_REPO) + + def sup_info(self): + return self.filter(_type=self.model.TYPE_SUP_INFO) diff --git a/scipost_django/journals/migrations/0135_alter_publicationresource__type.py b/scipost_django/journals/migrations/0135_alter_publicationresource__type.py new file mode 100644 index 000000000..93516ca8c --- /dev/null +++ b/scipost_django/journals/migrations/0135_alter_publicationresource__type.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.10 on 2024-08-05 13:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("journals", "0134_journal_alternative_journals"), + ] + + operations = [ + migrations.AlterField( + model_name="publicationresource", + name="_type", + field=models.CharField( + choices=[ + ("source_repo", "Publication source files repository"), + ("release_repo", "Codebase release version (archive) repository"), + ("live_repo", "Live (external) repository"), + ("supplemental_info", "Supplemental information"), + ], + max_length=32, + ), + ), + ] diff --git a/scipost_django/journals/models/resource.py b/scipost_django/journals/models/resource.py index 30580074d..ecc10045e 100644 --- a/scipost_django/journals/models/resource.py +++ b/scipost_django/journals/models/resource.py @@ -11,10 +11,12 @@ class PublicationResource(models.Model): TYPE_SOURCE_REPO = "source_repo" TYPE_RELEASE_ARCHIVE_REPO = "release_repo" TYPE_LIVE_REPO = "live_repo" + TYPE_SUP_INFO = "supplemental_info" TYPE_CHOICES = ( (TYPE_SOURCE_REPO, "Publication source files repository"), (TYPE_RELEASE_ARCHIVE_REPO, "Codebase release version (archive) repository"), (TYPE_LIVE_REPO, "Live (external) repository"), + (TYPE_SUP_INFO, "Supplemental information"), ) _type = models.CharField(max_length=32, choices=TYPE_CHOICES) publication = models.ForeignKey( diff --git a/scipost_django/journals/templates/journals/manage_publication_resources.html b/scipost_django/journals/templates/journals/manage_publication_resources.html index 5a400bcda..e3045e99e 100644 --- a/scipost_django/journals/templates/journals/manage_publication_resources.html +++ b/scipost_django/journals/templates/journals/manage_publication_resources.html @@ -26,6 +26,10 @@ <div hx-get="{% url "journals:_hx_publication_resource_list" doi_label=publication.doi_label %}" hx-trigger="load once"></div> - <a class="btn btn-sm btn-primary" - href="{{ publication.get_absolute_url }}">Back to Publication</a> + <div class="d-flex flex-row"> + <a class="btn btn-sm btn-secondary" + href="{{ publication.get_absolute_url }}">Back to Publication</a> + <a class="btn btn-sm btn-primary ms-auto" + href="{% url "journals:fetch_publication_resources" publication.doi_label %}">Fetch from preprint server</a> + </div> {% endblock content %} diff --git a/scipost_django/journals/templates/journals/publication_detail.html b/scipost_django/journals/templates/journals/publication_detail.html index bcd95c126..9c8e1c6fd 100644 --- a/scipost_django/journals/templates/journals/publication_detail.html +++ b/scipost_django/journals/templates/journals/publication_detail.html @@ -85,38 +85,56 @@ {% endif %} <hr class="mt-5 mb-4"/> - {% if publication.topics.all or perms.scipost.can_manage_ontology %} - <h3 class="mt-2">Ontology / Topics</h3> - See full <a href="{% url 'ontology:ontology' %}">Ontology</a> or <a href="{% url 'ontology:topics' %}">Topics</a> database. - <br> - <br> - - <div> - {% for topic in publication.topics.all %} - <span class="label label-secondary"><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a>{% if perms.scipost.can_manage_ontology %} <a href="{% url 'journals:publication_remove_topic' doi_label=publication.doi_label slug=topic.slug %}"><span class="text-danger">{% include 'bi/x-circle-fill.html' %}</span></a>{% endif %}</span> - {% empty %} - <div>No Topic has yet been associated to this Publication</div> - {% endfor %} - </div> + <div class="row"> + <div class="col"> + {% if publication.topics.all or perms.scipost.can_manage_ontology %} + <h3 class="mt-2">Ontology / Topics</h3> + See full <a href="{% url 'ontology:ontology' %}">Ontology</a> or <a href="{% url 'ontology:topics' %}">Topics</a> database. + <br> + <br> - {% if perms.scipost.can_manage_ontology %} - - <br> - <ul class="list-inline"> - <li class="list-inline-item"> - <form class="form-inline" action="{% url 'journals:publication_add_topic' doi_label=publication.doi_label %}" method="post"> - <ul class="list-inline"> - <li class="list-inline-item">Add an existing Topic:</li> - <li class="list-inline-item">{% csrf_token %}{{ select_topic_form }}</li> - <li class="list-inline-item"><input class="btn btn-outline-secondary" type="submit" value="Link"></li> - </ul> - </form> - </li> - <li class="list-inline-item p-2">Can't find the Topic you need? <a href="{% url 'ontology:topic_create' %}" target="_blank">Create it</a> (opens in new window)</li> - </ul> - {% endif %} + <div> + {% for topic in publication.topics.all %} + <span class="label label-secondary"><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a>{% if perms.scipost.can_manage_ontology %} <a href="{% url 'journals:publication_remove_topic' doi_label=publication.doi_label slug=topic.slug %}"><span class="text-danger">{% include 'bi/x-circle-fill.html' %}</span></a>{% endif %}</span> + {% empty %} + <div>No Topic has yet been associated to this Publication</div> + {% endfor %} + </div> - {% endif %} + {% if perms.scipost.can_manage_ontology %} + + <br> + <ul class="list-inline"> + <li class="list-inline-item"> + <form class="form-inline" action="{% url 'journals:publication_add_topic' doi_label=publication.doi_label %}" method="post"> + <ul class="list-inline"> + <li class="list-inline-item">Add an existing Topic:</li> + <li class="list-inline-item">{% csrf_token %}{{ select_topic_form }}</li> + <li class="list-inline-item"><input class="btn btn-outline-secondary" type="submit" value="Link"></li> + </ul> + </form> + </li> + <li class="list-inline-item p-2">Can't find the Topic you need? <a href="{% url 'ontology:topic_create' %}" target="_blank">Create it</a> (opens in new window)</li> + </ul> + {% endif %} + + {% endif %} + </div> + {% if publication.resources.sup_info %} + <div class="col-12 col-md col-xl-4"> + <details {% if publication.resources.sup_info|length < 4 %}open{% endif %} + class="hcard hcard-secondary bg-opacity-25"> + <summary class="list-triangle"><h3>Supplemental Information</h3></summary> + <p class="text-muted">External links to supplemental resources; opens in a new tab.</p> + <ul class="list-unstyled"> + {% for sup_info in publication.resources.sup_info.all %} + <li><a class="fs-6" href="{{ sup_info.url }}" target="_blank">{{ sup_info.comments }}</a></li> + {% endfor %} + </ul> + </details> + </div> + {% endif %} + </div> <h3 class="mt-4"> Author{{ publication.authors.all|length|pluralize }} / Affiliation{{ affiliations_list|length|pluralize }}: mappings to Contributors and Organizations diff --git a/scipost_django/journals/urls/general.py b/scipost_django/journals/urls/general.py index d258dd286..93f940bec 100644 --- a/scipost_django/journals/urls/general.py +++ b/scipost_django/journals/urls/general.py @@ -218,6 +218,11 @@ urlpatterns = [ journals_views.HTMXInlinePublicationResourceListView.as_view(), name="_hx_publication_resource_list", ), + path( + "admin/<publication_doi_label:doi_label>/fetch_publication_resources", + journals_views.fetch_publication_resources, + name="fetch_publication_resources", + ), # Admin: Volumes and Issues path( "admin/volumes/", diff --git a/scipost_django/journals/views.py b/scipost_django/journals/views.py index d6f18a81d..36ddd23f6 100644 --- a/scipost_django/journals/views.py +++ b/scipost_django/journals/views.py @@ -735,14 +735,62 @@ def draft_accompanying_publication(request, doi_label): @permission_required("scipost.can_draft_publication", raise_exception=True) def manage_publication_resources(request, doi_label): publication = get_object_or_404(Publication, doi_label=doi_label) + + # Determine whether to display button with automatic creation of resource + # Currently, only possible for ChemaRxiv submissions + can_fetch_resources = ( + "chemrxiv" + in publication.accepted_submission.preprint.identifier_w_vn_nr.lower() + ) + context = { "publication": publication, + "can_fetch_resources": can_fetch_resources, } return TemplateResponse( request, "journals/manage_publication_resources.html", context ) +def fetch_publication_resources(request, doi_label): + publication = get_object_or_404(Publication, doi_label=doi_label) + if ( + "chemrxiv" + not in publication.accepted_submission.preprint.identifier_w_vn_nr.lower() + ): + messages.error( + request, "Resource fetching is only available for ChemRxiv submissions" + ) + return redirect( + reverse("journals:manage_publication_resources", args=(doi_label,)) + ) + + # Fetch resources from ChemRxiv + response = requests.get( + f"https://chemrxiv.org/engage/chemrxiv/public-api/v1/items/doi/" + + publication.accepted_submission.preprint.identifier_w_vn_nr + ) + + if response.status_code != 200: + messages.error(request, "Resource fetching failed.") + return redirect( + reverse("journals:manage_publication_resources", args=(doi_label,)) + ) + + if resources := response.json().get("suppItems", []): + resources = sorted(resources, key=lambda x: x.get("id")) + + for resource in resources: + PublicationResource.objects.get_or_create( + publication=publication, + comments=resource.get("title"), + url=resource.get("asset", {}).get("original", {}).get("url", ""), + _type=PublicationResource.TYPE_SUP_INFO, + ) + + return redirect(reverse("journals:manage_publication_resources", args=(doi_label,))) + + @method_decorator(login_required, name="dispatch") @method_decorator( permission_required("scipost.can_draft_publication", raise_exception=True), -- GitLab