diff --git a/frontend/components/software/edit/contributors/index.tsx b/frontend/components/software/edit/contributors/index.tsx index ac56f3d2e..cdf729b3d 100644 --- a/frontend/components/software/edit/contributors/index.tsx +++ b/frontend/components/software/edit/contributors/index.tsx @@ -18,7 +18,6 @@ import { getAvatarUrl, getContributorsForSoftware, prepareContributorData, updateContributorInDb } from '~/utils/editContributors' -import useOnUnsaveChange from '~/utils/useOnUnsavedChange' import {getDisplayName} from '~/utils/getDisplayName' import {sortOnStrProp} from '~/utils/sortFn' import {getPropsFromObject} from '~/utils/getPropsFromObject' diff --git a/frontend/components/software/edit/information/index.tsx b/frontend/components/software/edit/information/index.tsx index 82e781ac2..fbcd290e6 100644 --- a/frontend/components/software/edit/information/index.tsx +++ b/frontend/components/software/edit/information/index.tsx @@ -69,7 +69,7 @@ export default function SoftwareInformation({slug}: {slug: string}) { id: initalState.id, slug: initalState.slug, brand_name: initalState.brand_name, - concept_doi: initalState.concept_doi + concept_doi: initalState.concept_doi, }) setLoading(false) } @@ -110,11 +110,20 @@ export default function SoftwareInformation({slug}: {slug: string}) { }) // if OK if (resp.status === 200) { - showSuccessMessage(`${formData?.brand_name} saved`) // reload software from api (confirm all changes saved and retreive new ids) - const updated = await getSoftwareInfoForEdit({slug,token}) - // update local state (useEffect will then reset form to new values) - setEditSoftware(updated) + const updated = await getSoftwareInfoForEdit({slug, token}) + if (updated) { + // update local state (useEffect will then reset form to new values) + setEditSoftware(updated) + // update shared software info + setSoftwareInfo({ + id: updated.id, + slug: updated.slug, + brand_name: updated.brand_name, + concept_doi: updated.concept_doi, + }) + } + showSuccessMessage(`${formData?.brand_name} saved`) } else { showErrorMessage(`Failed to save. ${resp.message}`) } diff --git a/frontend/components/software/edit/organisations/index.tsx b/frontend/components/software/edit/organisations/index.tsx index 63c77bbcd..46efa8955 100644 --- a/frontend/components/software/edit/organisations/index.tsx +++ b/frontend/components/software/edit/organisations/index.tsx @@ -160,7 +160,7 @@ export default function SoftwareOganisations() { // if it has id if (organisation?.id) { const resp = await deleteOrganisationFromSoftware({ - software: software?.id, + software: software?.id ?? undefined, organisation: organisation.id, token }) diff --git a/frontend/utils/getInfoFromDatacite.test.ts b/frontend/utils/getInfoFromDatacite.test.ts index c524d6579..3023c2038 100644 --- a/frontend/utils/getInfoFromDatacite.test.ts +++ b/frontend/utils/getInfoFromDatacite.test.ts @@ -115,241 +115,195 @@ const exampleResponse = { // taken from (and slightly modified): // https://github.com/inveniosoftware/datacite/blob/b15db91e1231135e5f2dba0cadca0c72ede037cf/tests/data/datacite-v4.1-full-example.json const dataciteFullExample = { - 'identifier': { - 'identifier': '10.1234/example-full', - 'identifierType': 'DOI' + 'id': 'https://doi.org/10.5880/riesgos.2021.003', + 'doi': '10.5880/RIESGOS.2021.003', + 'url': 'https://dataservices.gfz-potsdam.de/panmetaworks/showshort.php?id=bae8fc94-4799-11ec-947f-3811b03e280f', + 'types': { + 'ris': 'COMP', + 'bibtex': 'misc', + 'citeproc': 'article', + 'schemaOrg': 'SoftwareSourceCode', + 'resourceType': 'Software', + 'resourceTypeGeneral': 'Software' }, 'creators': [ { - 'creatorName': 'Miller, Elizabeth', + 'name': 'Pittore, Massimiliano', 'nameType': 'Personal', - 'givenName': 'Elizabeth', - 'familyName': 'Miller', - 'nameIdentifiers': [ + 'givenName': 'Massimiliano', + 'familyName': 'Pittore', + 'affiliation': [ { - 'nameIdentifier': '0000-0000-0000-0000', - 'nameIdentifierScheme': 'ORCID', - 'schemeURI': 'http://orcid.org/' + 'name': 'GFZ German Research Centre for Geosciences, Potsdam, Germany', + 'affiliationIdentifierScheme': 'ORCID' }, { - 'nameIdentifier': '0000-0000-0000-0001', - 'nameIdentifierScheme': 'ORCID', - 'schemeURI': 'http://orcid.org/' + 'name': 'EURAC Research (Accademia Europea): Bolzano, Trentino-Alto Adige, Italy' } ], - 'affiliation': ['DataCite', 'CERN', 'TIND'] - } - ], - 'titles': [ - { - 'title': 'Full DataCite XML Example', - 'lang': 'en-us' + 'nameIdentifiers': [ + { + 'schemeUri': 'https://orcid.org', + 'nameIdentifier': 'https://orcid.org/0000-0003-4940-3444', + 'nameIdentifierScheme': 'ORCID' + } + ] }, { - 'title': 'Demonstration of DataCite Properties.', - 'titleType': 'Subtitle', - 'lang': 'en-us' - } - ], - 'publisher': 'DataCite', - 'publicationYear': '2014', - 'subjects': [ - { - 'subject': '000 computer science', - 'subjectScheme': 'dewey', - 'valueURI': 'https://cern.ch', - 'schemeURI': 'http://dewey.info/', - 'lang': 'en-us' - } - ], - 'contributors': [ - { - 'contributorName': 'Starr, Joan', + 'name': 'Haas, Michael', 'nameType': 'Personal', - 'contributorType': 'ProjectLeader', - 'givenName': 'Joan', - 'familyName': 'Starr', - 'nameIdentifiers': [ + 'givenName': 'Michael', + 'familyName': 'Haas', + 'affiliation': [ { - 'nameIdentifier': '1000-0000-0000-000X', - 'nameIdentifierScheme': 'ORCID', - 'schemeURI': 'http://orcid.org/' + 'name': 'Formerly at GFZ German Research Centre for Geosciences, Potsdam, Germany' } ], - 'affiliation': ['California Digital Library'] + 'nameIdentifiers': [ + { + 'schemeUri': 'https://orcid.org', + 'nameIdentifier': 'https://orcid.org/0000-0002-1179-1659', + 'nameIdentifierScheme': 'ORCID' + } + ] } ], - 'dates': [ + 'titles': [ { - 'date': '2014-10-17', - 'dateType': 'Updated', - 'dateInformation': 'Date of the first publishing.' + 'title': 'Quakeledger: a web service to serve earthquake scenarios' } ], - 'language': 'en-us', - 'resourceType': { - 'resourceTypeGeneral': 'Software', - 'resourceType': 'XML' - }, - 'alternateIdentifiers': [ + 'publisher': 'GFZ Data Services', + 'container': {}, + 'subjects': [ { - 'alternateIdentifier': 'http://schema.datacite.org/schema/meta/kernel-4.1/example/datacite-example-full-v4.1.xml', - 'alternateIdentifierType': 'URL' - } - ], - 'relatedIdentifiers': [ + 'subject': 'Earthquake catalogue' + }, { - 'relatedIdentifier': 'http://data.datacite.org/application/citeproc+json/10.1234/example-full', - 'relatedIdentifierType': 'URL', - 'relationType': 'HasMetadata', - 'relatedMetadataScheme': 'citeproc+json', - 'schemeURI': 'https://github.com/citation-style-language/schema/raw/master/csl-data.json' + 'subject': 'provider' }, { - 'relatedIdentifier': 'arXiv:0706.0001', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'IsReviewedBy' + 'subject': 'script' }, { - 'relatedIdentifier': 'arXiv:0706.0002', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'IsDescribedBy', - 'resourceTypeGeneral': 'Text' + 'subject': 'python' }, { - 'relatedIdentifier': 'arXiv:0706.0003', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'Describes' + 'subject': 'RIESGOS' }, { - 'relatedIdentifier': 'arXiv:0706.0004', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'IsVersionOf' + 'subject': 'Scenario-based multi-risk assessment in the Andes region' }, { - 'relatedIdentifier': 'arXiv:0706.0005', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'HasVersion' + 'subject': 'EARTH SCIENCE SERVICES > DATA ANALYSIS AND VISUALIZATION', + 'subjectScheme': 'NASA/GCMD Earth Science Keywords' }, { - 'relatedIdentifier': 'arXiv:0706.0006', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'IsRequiredBy' + 'subject': 'EARTH SCIENCE SERVICES > DATA MANAGEMENT/DATA HANDLING', + 'subjectScheme': 'NASA/GCMD Earth Science Keywords' }, { - 'relatedIdentifier': 'arXiv:0706.0007', - 'relatedIdentifierType': 'arXiv', - 'relationType': 'Requires' + 'subject': 'EARTH SCIENCE SERVICES > WEB SERVICES', + 'subjectScheme': 'NASA/GCMD Earth Science Keywords' + }, + { + 'subject': 'EARTH SCIENCE SERVICES > WEB SERVICES > DATA PROCESSING SERVICES', + 'subjectScheme': 'NASA/GCMD Earth Science Keywords' } ], - 'sizes': [ - '3KB' + 'contributors': [ + { + 'name': 'Haas, Michael', + 'nameType': 'Personal', + 'givenName': 'Michael', + 'familyName': 'Haas', + 'affiliation': [ + { + 'name': 'Formerly at GFZ German Research Centre for Geosciences, Potsdam, Germany' + } + ], + 'nameIdentifiers': [ + { + 'schemeUri': 'https://orcid.org', + 'nameIdentifier': 'https://orcid.org/0000-0002-1179-1659', + 'nameIdentifierScheme': 'ORCID' + } + ] + }, ], - 'formats': [ - 'application/xml' + 'dates': [ + { + 'date': '2021', + 'dateType': 'Issued' + } ], - 'version': '4.1', + 'publicationYear': 2021, + 'identifiers': [], + 'sizes': [], + 'formats': [], + 'version': '1.0', 'rightsList': [ { - 'rights': 'CC0 1.0 Universal', - 'rightsURI': 'http://creativecommons.org/publicdomain/zero/1.0/', - 'lang': 'en-us' + 'rights': 'BSD 3-Clause "New" or "Revised" License', + 'rightsUri': 'https://opensource.org/licenses/BSD-3-Clause', + 'schemeUri': 'https://spdx.org/licenses/', + 'rightsIdentifier': 'bsd-3-clause', + 'rightsIdentifierScheme': 'SPDX' } ], 'descriptions': [ { - 'descriptionType': 'Abstract', - 'lang': 'en-us', - 'description': 'XML example of all DataCite Metadata Schema v4.1 properties.' + 'description': 'This version of Quakeledger (V.1.0) is a Python3 program that can also be used as a WPS (Web Processing Service). It returns the available earthquake events contained within a given local database (so called catalogue) that must be customised beforehand (e.g. historical, expert and/or stochastic events). This is a rewrite from: https://github.com/GFZ-Centre-for-Early-Warning/quakeledger and https://github.com/bpross-52n/quakeledger. In these original codes, an earthquake catalogue had to be initially provided in .CSV format. The main difference with this version is that, this code is refactored and uses a SQLITE database. The user can find the parser code in: “quakeledger/assistance/import_csv_in_sqlite.py”', + 'descriptionType': 'Abstract' + }, + { + 'description': 'License: BSD 3-Clause Copyright © 2021 Early Warning and Impact Assessment Group at Helmholtz Centre Potsdam GFZ German Research Centre for Geosciences Quakeledger is free software: you can redistribute it and/or modify it under the terms of the BSD 3-Clause License. Quakeledger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the BSD 3-Clause License for more details. You should have received a copy of the BSD 3-Clause License along with this program. If not, see', + 'descriptionType': 'Other' } ], + 'geoLocations': [], 'fundingReferences': [ { - 'funderName': 'European Commission', - 'funderIdentifier': { - 'funderIdentifier': 'http://doi.org/10.13039/501100000780', - 'funderIdentifierType': 'Crossref Funder ID' - }, - 'awardNumber': { - 'awardNumber': '282625', - 'awardURI': 'http://cordis.europa.eu/project/rcn/100180_en.html' - }, - 'awardTitle': 'MOTivational strength of ecosystem services and alternative ways to express the value of BIOdiversity' + 'awardTitle': 'LIENT II – International Partnerships for Sustainable Innovations- RIESGOS', + 'funderName': 'Bundesministerium für Bildung und Forschung', + 'awardNumber': '03G0876', + 'funderIdentifier': 'https://doi.org/10.13039/501100002347', + 'funderIdentifierType': 'Crossref Funder ID' + } + ], + 'relatedIdentifiers': [ + { + 'relationType': 'References', + 'relatedIdentifier': '10.1785/0220130087', + 'relatedIdentifierType': 'DOI' }, { - 'funderName': 'European Commission', - 'funderIdentifier': { - 'funderIdentifier': 'http://doi.org/10.13039/501100000780', - 'funderIdentifierType': 'Crossref Funder ID' - }, - 'awardNumber': { - 'awardNumber': '284382', - 'awardURI': 'http://cordis.europa.eu/project/rcn/100603_en.html' - }, - 'awardTitle': 'Institutionalizing global genetic-resource commons. Global Strategies for accessingand using essential public knowledge assets in the life science' + 'relationType': 'References', + 'relatedIdentifier': 'https://www.riesgos.de/en/', + 'relatedIdentifierType': 'URL' + }, + { + 'relationType': 'IsNewVersionOf', + 'relatedIdentifier': 'https://github.com/GFZ-Centre-for-Early-Warning/quakeledger', + 'relatedIdentifierType': 'URL' + }, + { + 'relationType': 'IsNewVersionOf', + 'relatedIdentifier': 'https://github.com/bpross-52n/quakeledger', + 'relatedIdentifierType': 'URL' + }, + { + 'relationType': 'IsVariantFormOf', + 'relatedIdentifier': 'https://github.com/gfzriesgos/quakeledger/', + 'relatedIdentifierType': 'URL' } ], - 'geoLocations': [ - { - 'geoLocationPoint': { - 'pointLongitude': 31.233, - 'pointLatitude': -67.302 - }, - 'geoLocationBox': { - 'westBoundLongitude': -71.032, - 'eastBoundLongitude': -68.211, - 'southBoundLatitude': 41.090, - 'northBoundLatitude': 42.893 - }, - 'geoLocationPlace': 'Atlantic Ocean', - 'geoLocationPolygons': [ - { - 'polygonPoints': [ - { - 'pointLongitude': -71.032, - 'pointLatitude': 41.090 - }, - { - 'pointLongitude': -68.211, - 'pointLatitude': 42.893 - }, - { - 'pointLongitude': -72.032, - 'pointLatitude': 39.090 - }, - { - 'pointLongitude': -71.032, - 'pointLatitude': 41.090 - } - ] - }, - { - 'polygonPoints': [ - { - 'pointLongitude': -72.032, - 'pointLatitude': 42.090 - }, - { - 'pointLongitude': -69.211, - 'pointLatitude': 43.893 - }, - { - 'pointLongitude': -73.032, - 'pointLatitude': 41.090 - }, - { - 'pointLongitude': -72.032, - 'pointLatitude': 42.090 - } - ], - 'inPolygonPoint': { - 'pointLongitude': -52.032, - 'pointLatitude': 12.090 - } - } - ] - } - ] + 'relatedItems': [], + 'schemaVersion': 'http://datacite.org/schema/kernel-4', + 'providerId': 'gfz', + 'clientId': 'tib.gfz', + 'agency': 'datacite', + 'state': 'findable' } const exampleResponseInvalidPersons = { @@ -475,33 +429,31 @@ it('returns expected contributors', async () => { ) }) -it('returns authors and contributors', async () => { +it.only('returns authors and contributors (without duplicates)', async () => { mockResolvedValueOnce(dataciteFullExample) + const expectedList = [ + { + given_names: 'Massimiliano', + family_names: 'Pittore', + email_address: '', + software: '0', + affiliation: 'GFZ German Research Centre for Geosciences, Potsdam, Germany', + is_contact_person: false, + orcid: '0000-0003-4940-3444' + }, + { + given_names: 'Michael', + family_names: 'Haas', + email_address: '', + software: '0', + affiliation: 'Formerly at GFZ German Research Centre for Geosciences, Potsdam, Germany', + is_contact_person: false, + orcid: '0000-0002-1179-1659' + } + ] const resp = await getContributorsFromDoi('0', 'DOI') - - expect(resp).toEqual( - [ - { - 'affiliation': 'DataCite', - 'email_address': '', - 'family_names': 'Miller', - 'given_names': 'Elizabeth', - 'is_contact_person': false, - 'orcid': '0000-0000-0000-0000', - 'software': '0' - }, - { - 'affiliation': 'California Digital Library', - 'email_address': '', - 'family_names': 'Starr', - 'given_names': 'Joan', - 'is_contact_person': false, - 'orcid': '1000-0000-0000-000X', - 'software': '0' - } - ] - ) + expect(resp).toEqual(expectedList) }) it('skips invalid persons', async () => { diff --git a/frontend/utils/getInfoFromDatacite.ts b/frontend/utils/getInfoFromDatacite.ts index e24fc20a2..86e933f99 100644 --- a/frontend/utils/getInfoFromDatacite.ts +++ b/frontend/utils/getInfoFromDatacite.ts @@ -7,6 +7,7 @@ import {Contributor} from '~/types/Contributor' import {createJsonHeaders} from './fetchHelpers' +import {itemsNotInReferenceList} from './itemsNotInReferenceList' import logger from './logger' const exampleCreator = { @@ -164,11 +165,19 @@ export async function getContributorsFromDoi( let allPersons: DatacitePerson[] = [] if ('creators' in doiData) { - allPersons = allPersons.concat(doiData['creators']) + allPersons = doiData['creators'] } if ('contributors' in doiData) { - allPersons = allPersons.concat(doiData['contributors']) + const contributors = itemsNotInReferenceList({ + list: doiData['contributors'], + referenceList: allPersons, + key: 'name' + }) + allPersons = [ + ...allPersons, + ...contributors + ] } for (const person of allPersons) {