diff --git a/dalima/settings.py b/dalima/settings.py index ada06da6e3562c64e8d0f0eb89b8d71af08ba9df..2e037bd275c383c4cc9d20bd86c2fcfd2b39a662 100644 --- a/dalima/settings.py +++ b/dalima/settings.py @@ -178,6 +178,7 @@ DATACITE_TIMEOUT = env.int("DATACITE_TIMEOUT", 10) DATACITE_DEFAULT_PUBLISHER_ID = env.str( "DATACITE_DEFAULT_PUBLISHER_ID", "https://www.re3data.org/repository/r3d100012222" ) +DATACITE_DOI_TEST_SUFFIX = env.str("DATACITE_DOI_TEST_SUFFIX", "_test") # DC DC_URL = env.str("DC_URL") diff --git a/datacite/datacite.py b/datacite/datacite.py index 31dfecc5455e705389cdb2e2f4dce869737f03c6..04a8b6f306a4afb70b0d72a5bc31be143aa123aa 100644 --- a/datacite/datacite.py +++ b/datacite/datacite.py @@ -1,5 +1,4 @@ import logging -from http import HTTPStatus from typing import Any import humps @@ -38,7 +37,7 @@ class DataciteRESTClient: timeout=DATACITE_TIMEOUT, auth=authentication, ) - if resp.status_code == HTTPStatus.OK: + if resp.status_code == requests.codes.ok: logger.info( "Fetched metadata for %s from Datacite.", doi if doi else "__all__" ) diff --git a/datacite/fdsn.py b/datacite/fdsn.py index 2cd5a481b629e541c9782465665a94aaa9bc1397..d273fea4d10041188be79c026fd6378aa22ab5db 100644 --- a/datacite/fdsn.py +++ b/datacite/fdsn.py @@ -1,5 +1,4 @@ import logging -from http import HTTPStatus from typing import Any import requests @@ -28,7 +27,7 @@ class FdsnRESTClient: params=params, timeout=1, ) - if resp.status_code == HTTPStatus.OK: + if resp.status_code == requests.codes.ok: logger.info("Fetched the list of networks from FDSN.") return resp.json()["networks"] logger.warning("Failed to fetched the list of networks from FDSN.") diff --git a/datacite/static/datacite/metadata_form.js b/datacite/static/datacite/metadata_form.js index eaa39ce1c14f7ff77591b5c93b1ccf502a805c0a..ad74e718a85520893d4b0eac925cebdb396590af 100644 --- a/datacite/static/datacite/metadata_form.js +++ b/datacite/static/datacite/metadata_form.js @@ -10,8 +10,8 @@ function updateOptions(item, array) { item.addOptions(array); } -document.body.addEventListener("creatorListChanged", function (evt) { - updateOptions(select, evt.detail.value); +document.body.addEventListener("creatorListChanged", function (event) { + updateOptions(select, event.detail.value); }); @@ -39,22 +39,22 @@ function organizeCreatorForm() { } -htmx.on("htmx:afterSwap", (e) => { +htmx.on("htmx:afterSwap", (event) => { // Response targeting #dialog => show the modal - if (e.detail.target.id == "creator-form-container") { + if (event.detail.target.id == "creator-form-container") { modal.show(); organizeCreatorForm(); } }); -htmx.on("htmx:beforeSwap", (e) => { +htmx.on("htmx:beforeSwap", (event) => { // Empty response targeting #dialog => hide the modal if ( - e.detail.target.id == "creator-form-container" && - !e.detail.xhr.response + event.detail.target.id == "creator-form-container" && + !event.detail.xhr.response ) { modal.hide(); - e.detail.shouldSwap = false; + event.detail.shouldSwap = false; } }); diff --git a/datacite/tests/conftest.py b/datacite/tests/conftest.py index 292c0dd4ffbab5a4e9153ca4eb95ba639f9fbbdb..042fb620e15a4694868f025ebe6b4868b593ba8a 100644 --- a/datacite/tests/conftest.py +++ b/datacite/tests/conftest.py @@ -310,5 +310,8 @@ def datacite_bad_response(): response.code = "expired" response.error_type = "expired" response.status_code = 400 - response._content = b'{ "key" : "a" }' # noqa: SLF001 + response._content = ( # noqa: SLF001 + b'{ "errors" : [{"source": "a", "title": "blabla [xx] error ' + b'description. at line xx " }]}' + ) return response diff --git a/datacite/tests/views_tests.py b/datacite/tests/views_tests.py index 8ee6596f628da00b6469e9d29267d19979a1afd7..8fc894db7d8fdbbb5b2fd0824591ab1256a7b91b 100644 --- a/datacite/tests/views_tests.py +++ b/datacite/tests/views_tests.py @@ -1,6 +1,4 @@ # ruff: noqa: S101 -from http import HTTPStatus - import pytest import requests.exceptions from crispy_forms.helper import FormHelper @@ -79,7 +77,7 @@ def test_metadata_detail__post__invalid_publish(mocker, client, datacite_bad_res expected_messages = [ Message( messages.ERROR, - 'Could not publish the metadata in Datacite 400 : { "key" : "a" }', + "\t\u27a5 a --> error description.", ) ] @@ -154,7 +152,7 @@ def test_creator_create__form_valid(client): ) assert len(Creator.objects.all()) == 1 - assert response.status_code == HTTPStatus.NO_CONTENT + assert response.status_code == requests.codes.no_content assert "HX-Trigger" in response.headers diff --git a/datacite/utils.py b/datacite/utils.py index a8a995309cc4c2d550fee5e577bb6066850bba96..36ea8d8cf35bc67ad2c2b2b2aac64807f05ca2cf 100644 --- a/datacite/utils.py +++ b/datacite/utils.py @@ -26,3 +26,16 @@ def get_languages() -> list[tuple[str, str]]: for lang in pycountry.languages if hasattr(lang, "alpha_2") ] + + +def format_error_from_datacite(error: dict) -> str: + """ + Formats the error from datacite to print them as messages. + :param error: error from datacite + :return: the formated error + """ + try: + description = error["title"].split("]")[1].split(" at line")[0] + except IndexError: + description = error["title"] + return f"\t\u27a5 {error['source']} --> {description}" diff --git a/datacite/views.py b/datacite/views.py index 92f88206a980b72a93fa6bfc4becb7e226900c03..4075468458a50601003043fec413f7f5b6f3aaea 100644 --- a/datacite/views.py +++ b/datacite/views.py @@ -31,6 +31,8 @@ from datacite.serializers import ( MetadataSerializer, TitleSerializer, ) +from datacite.utils import format_error_from_datacite +from network.models import Network logger = logging.getLogger(__name__) @@ -60,14 +62,41 @@ class MetadataDetail(DetailView): messages.success( self.request, "Successfully published the metadata in Datacite" ) - except requests.exceptions.HTTPError as err: - logger.warning("Failed to upsert metadata for %s from Datacite.", doi) + except ( + requests.exceptions.ConnectionError, + requests.exceptions.Timeout, + requests.exceptions.TooManyRedirects, + ): + message = "Connection error with datacite.org" + logger.warning( + "Failed to upsert metadata for %s from Datacite : %s", + doi, + message, + ) messages.error( - self.request, - "Could not publish the metadata in Datacite " - f"{err.response.status_code} : " - f"{err.response.content.decode()}", + self.request, f"Could not publish the metadata in Datacite : {message}" ) + except requests.exceptions.HTTPError as exception: + if ( + requests.codes.bad_request + <= exception.response.status_code + < requests.codes.server_error + ): + logger.warning("Failed to upsert metadata for %s from Datacite.", doi) + for error in exception.response.json()["errors"]: + messages.error( + self.request, + format_error_from_datacite(error), + ) + else: + message = "Server error from datacite.org" + logger.warning( + "Failed to upsert metadata for %s from Datacite : %s", doi, message + ) + messages.error( + self.request, + f"Could not publish the metadata in Datacite : {message}", + ) return response @@ -95,7 +124,11 @@ class MetadataCreate(SuccessMessageWithInlinesMixin, CreateWithInlinesView): kwargs = super().get_form_kwargs() params = self.request.GET.dict() if "network_id" in params and params["network_id"].isdigit(): - kwargs["initial"]["network_id"] = int(params["network_id"]) + network_id = int(params["network_id"]) + kwargs["initial"]["network_id"] = network_id + kwargs["initial"]["doi"] = Network.objects.get(pk=network_id).doi + if settings.DEBUG: + kwargs["initial"]["doi"] += settings.DATACITE_DOI_TEST_SUFFIX return kwargs diff --git a/templates/alert.html b/templates/flash_message.html similarity index 100% rename from templates/alert.html rename to templates/flash_message.html diff --git a/templates/flash_messages.html b/templates/flash_messages.html index 5973f4d622079f02d1467984f63ec397bc5e10cf..81664caecdb936e58dbc6fe186d50033b3feac4f 100644 --- a/templates/flash_messages.html +++ b/templates/flash_messages.html @@ -3,8 +3,8 @@ {% for message in messages %} {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %} - {% include "alert.html" with bootstrap_level="danger" %} + {% include "flash_message.html" with bootstrap_level="danger" %} {% else %} - {% include "alert.html" with bootstrap_level=message.tags %} + {% include "flash_message.html" with bootstrap_level=message.tags %} {% endif %} {% endfor %}