From a0a30959c85534fbc40a3ce8b51951ad0536fe71 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Wed, 1 Nov 2023 15:00:47 -0700 Subject: [PATCH 1/8] auto-populate Datacite Resource type general as 'Dataset' --- src/utils/recordToDataCite.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index 1e9959e4..31497ece 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -219,6 +219,10 @@ function recordToDataCite(metadata) { mappedDataCiteObject.data.attributes.geoLocations = geoLocations; } + // Auto-populate Datacite Resource type general as 'dataset' + mappedDataCiteObject.data.attributes.types = { + resourceTypeGeneral: "Dataset", + }; return mappedDataCiteObject; } From 90f718e197eee0594d937eca66244d777f7d5e96 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Wed, 1 Nov 2023 16:06:25 -0700 Subject: [PATCH 2/8] Fixed - author names not showing up in creator list --- src/utils/recordToDataCite.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index 31497ece..e34469fa 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -8,18 +8,20 @@ function recordToDataCite(metadata) { const creators = metadata.contacts ? metadata.contacts.reduce((creatorList, contact) => { let creator; - if (contact.inCitation) { + if (contact.inCitation && !contact.role.includes("publisher")) { const { indName, orgName, lastName, givenNames, + lastName, + orgName, indOrcid, orgRor, } = contact; - // Create an individual creator object if indName is present - if (indName) { + // Create an individual creator object with names + if (givenNames) { creator = { name: `${lastName}, ${givenNames}`, nameType: "Personal", From a87c85b6fa6bd2c321a9c12bc38f9f564d7e6203 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Thu, 2 Nov 2023 15:14:59 -0700 Subject: [PATCH 3/8] Generate URL for Datacite object --- src/components/Tabs/IdentificationTab.jsx | 2 +- src/utils/recordToDataCite.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/Tabs/IdentificationTab.jsx b/src/components/Tabs/IdentificationTab.jsx index d94207cf..91393fd5 100644 --- a/src/components/Tabs/IdentificationTab.jsx +++ b/src/components/Tabs/IdentificationTab.jsx @@ -82,7 +82,7 @@ const IdentificationTab = ({ setLoadingDoi(true); try { - const mappedDataCiteObject = recordToDataCite(record); + const mappedDataCiteObject = recordToDataCite(record, language, region); await createDraftDoi(mappedDataCiteObject) .then((response) => { return response.data.data.attributes; diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index e34469fa..e1a752ea 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -2,7 +2,7 @@ import licenses from "./licenses"; import regions from "../regions"; -function recordToDataCite(metadata) { +function recordToDataCite(metadata, language, region) { // Reduce contacts to a list of creators const creators = metadata.contacts ? metadata.contacts.reduce((creatorList, contact) => { @@ -224,7 +224,10 @@ function recordToDataCite(metadata) { // Auto-populate Datacite Resource type general as 'dataset' mappedDataCiteObject.data.attributes.types = { resourceTypeGeneral: "Dataset", - }; + }; + + // Generate URL element + mappedDataCiteObject.data.attributes.url = `${regions[region].catalogueURL[language]}dataset/ca-cioos_${metadata.identifier}`; return mappedDataCiteObject; } From b3fedb5d680fd01cc134636dceaaa2c2af3c7962 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Thu, 2 Nov 2023 15:16:15 -0700 Subject: [PATCH 4/8] set prefix dynamically based on region, instead of using hard coded region/org name. --- src/utils/recordToDataCite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index e1a752ea..3e2c05f7 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -159,7 +159,7 @@ function recordToDataCite(metadata, language, region) { data: { type: "dois", attributes: { - prefix: regions.hakai.datacitePrefix, + prefix: regions[region].datacitePrefix, creators, // Initialize an empty array for titles titles: [], From c2c5013357c40ecdf3c61a1a68b729a71fe4fd21 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Thu, 2 Nov 2023 15:47:21 -0700 Subject: [PATCH 5/8] fix author names and affilitations in creators list --- src/utils/recordToDataCite.js | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index 3e2c05f7..497a3bff 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -10,9 +10,6 @@ function recordToDataCite(metadata, language, region) { if (contact.inCitation && !contact.role.includes("publisher")) { const { - indName, - orgName, - lastName, givenNames, lastName, orgName, @@ -27,6 +24,13 @@ function recordToDataCite(metadata, language, region) { nameType: "Personal", givenName: givenNames, familyName: lastName, + // Add affiliation for individual if organization details are provided + affiliation: orgName ? [{ + name: orgName, + schemeUri: "https://ror.org", + affiliationIdentifier: orgRor, + affiliationIdentifierScheme: "ROR", + }] : [], }; // Add nameIdentifiers for individual with an ORCID @@ -40,25 +44,6 @@ function recordToDataCite(metadata, language, region) { ]; } } - - // Create an organizational creator object if orgName is present - if (orgName) { - creator = { - name: orgName, - nameType: "Organizational", - }; - - // Add nameIdentifiers for organization with a ROR - if (orgRor) { - creator.nameIdentifiers = [ - { - schemeUri: "https://ror.org", - nameIdentifier: orgRor, - nameIdentifierScheme: "ROR", - }, - ]; - } - } } // Add the creator to the list if it exists @@ -228,6 +213,7 @@ function recordToDataCite(metadata, language, region) { // Generate URL element mappedDataCiteObject.data.attributes.url = `${regions[region].catalogueURL[language]}dataset/ca-cioos_${metadata.identifier}`; + return mappedDataCiteObject; } From 82595d3f85d8d409036d100ff60721e529a0c329 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Fri, 3 Nov 2023 10:08:49 -0700 Subject: [PATCH 6/8] remove console logs --- src/utils/recordToDataCite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index 497a3bff..3360b03c 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -213,7 +213,7 @@ function recordToDataCite(metadata, language, region) { // Generate URL element mappedDataCiteObject.data.attributes.url = `${regions[region].catalogueURL[language]}dataset/ca-cioos_${metadata.identifier}`; - + return mappedDataCiteObject; } From 71ca90afde148f4b85067f80ed717c4d4c0a224e Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Fri, 3 Nov 2023 14:35:01 -0700 Subject: [PATCH 7/8] add unit test for recordToDataCite --- src/__testData__/expectedDataCiteStructure.js | 103 +++++++++++++++ src/__testData__/mockMetadataRecord.js | 119 ++++++++++++++++++ src/__tests__/recordToDataCite.test.js | 19 +++ src/utils/recordToDataCite.js | 4 + 4 files changed, 245 insertions(+) create mode 100644 src/__testData__/expectedDataCiteStructure.js create mode 100644 src/__testData__/mockMetadataRecord.js create mode 100644 src/__tests__/recordToDataCite.test.js diff --git a/src/__testData__/expectedDataCiteStructure.js b/src/__testData__/expectedDataCiteStructure.js new file mode 100644 index 00000000..ed05142d --- /dev/null +++ b/src/__testData__/expectedDataCiteStructure.js @@ -0,0 +1,103 @@ + +const expectedDataCiteStructure = { + "data": { + "type": "dois", + "attributes": { + "prefix": "10.21966", + "creators": [ + { + "name": "Sorochak, Austen", + "nameType": "Personal", + "givenName": "Austen", + "familyName": "Sorochak", + "affiliation": [ + { + "name": "Royal Roads University", + "schemeUri": "https://ror.org", + "affiliationIdentifier": "https://ror.org/05w4ste42", + "affiliationIdentifierScheme": "ROR", + }, + ], + }, + { + "name": "PumpkinKing, Jack", + "nameType": "Personal", + "givenName": "Jack", + "familyName": "PumpkinKing", + "affiliation": [], + }, + ], + "titles": [ + { + "lang": "en", + "title": "This is a mock record", + }, + { + "lang": "fr", + "title": "Il s'agit d'un faux record", + }, + ], + "publisher": "Royal Roads University", + "publicationYear": 2023, + "subjects": [ + { + "lang": "en", + "subject": "abundance and biomass", + }, + { + "lang": "fr", + "subject": "abondance et biomasse", + }, + ], + "dates": [ + { + "date": "2023-10-01T19:00:00.000Z", + "dateType": "Collected", + "dateInformation": "Start date when data was first collected", + }, + { + "date": "2023-10-04T19:00:00.000Z", + "dateType": "Collected", + "dateInformation": "End date when data was last collected", + }, + ], + "rightsList": [ + { + "rights": "Creative Commons Attribution 4.0 Attribution", + "rightsUri": "https://creativecommons.org/licenses/by/4.0", + "schemeUri": "https://spdx.org/licenses/", + "rightsIdentifier": "CC-BY-4.0", + "rightsIdentifierScheme": "SPDX", + }, + ], + "descriptions": [ + { + "lang": "en", + "description": "This is a mock record to be used in unit tests, to ensure the continued functionality of the mapping function.", + "descriptionType": "Abstract", + }, + { + "lang": "fr", + "description": "Il s'agit d'un enregistrement fictif à utiliser dans les tests unitaires, afin de garantir la fonctionnalité continue de la fonction de mappage.", + "descriptionType": "Abstract", + }, + ], + "geoLocations": [ + { + "geoLocationBox": { + "eastBoundLongitude": -160, + "northBoundLatitude": 60, + "southBoundLatitude": 45, + "westBoundLongitude": -120, + }, + }, + ], + "types": { + "resourceTypeGeneral": "Dataset", + }, + "url": "https://catalogue.hakai.org/dataset/ca-cioos_b6f44266-5815-48bb-bd0c-dd050c6fe465", + }, + }, +} + +export default expectedDataCiteStructure; \ No newline at end of file diff --git a/src/__testData__/mockMetadataRecord.js b/src/__testData__/mockMetadataRecord.js new file mode 100644 index 00000000..dd09e5de --- /dev/null +++ b/src/__testData__/mockMetadataRecord.js @@ -0,0 +1,119 @@ + +const mockMetadataRecord = { + "title": { + "en": "This is a mock record", + "fr": "Il s'agit d'un faux record", + }, + "abstract": { + "en": "This is a mock record to be used in unit tests, to ensure the continued functionality of the mapping function.", + "fr": "Il s'agit d'un enregistrement fictif à utiliser dans les tests unitaires, afin de garantir la fonctionnalité continue de la fonction de mappage.", + }, + "keywords": { + "en": [ + "abundance and biomass", + ], + "fr": [ + "abondance et biomasse", + ], + }, + "eov": [ + "dissolvedOrganicCarbon", + ], + "progress": "onGoing", + "distribution": [], + "dateStart": "2023-10-01T19:00:00.000Z", + "dateEnd": "2023-10-04T19:00:00.000Z", + "map": { + "east": "-160", + "north": "60", + "polygon": "", + "south": "45", + "west": "-120", + }, + "verticalExtentMin": "", + "verticalExtentMax": "", + "datePublished": "2023-10-26T19:00:00.000Z", + "dateRevised": null, + "edition": "", + "recordID": "-Nhi6_2lQjNwKkzdv_Qu", + "instruments": [], + "platform": "", + "platformID": "", + "platformDescription": "", + "language": "en", + "license": "CC-BY-4.0", + "contacts": [ + { + "role": [ + "custodian", + ], + "orgName": "Royal Roads University", + "orgEmail": "", + "orgURL": "http://www.royalroads.ca/", + "orgAdress": "", + "orgCity": "Victoria", + "orgCountry": "Canada", + "orgRor": "https://ror.org/05w4ste42", + "indPosition": "", + "indEmail": "", + "indOrcid": "", + "givenNames": "Austen", + "lastName": "Sorochak", + "inCitation": true, + }, + { + "role": [], + "orgName": "", + "orgEmail": "", + "orgURL": "", + "orgAdress": "", + "orgCity": "", + "orgCountry": "", + "orgRor": "", + "indPosition": "", + "indEmail": "", + "indOrcid": "", + "givenNames": "Jack", + "lastName": "PumpkinKing", + "inCitation": true, + }, + { + "role": [ + "publisher", + ], + "orgName": "Royal Roads University", + "orgEmail": "", + "orgURL": "", + "orgAdress": "", + "orgCity": "", + "orgCountry": "", + "orgRor": "", + "indPosition": "", + "indEmail": "", + "indOrcid": "", + "givenNames": "", + "lastName": "", + "inCitation": true, + }, + ], + "status": "", + "comment": "", + "limitations": "", + "lastEditedBy": { + "displayName": "Austen Sorochak", + "email": "austen.sorochak@hakai.org", + }, + "category": "", + "verticalExtentDirection": "", + "datasetIdentifier": "", + "doiCreationStatus": "", + "noPlatform": false, + "filename": "", + "organization": "", + "timeFirstPublished": "", + "identifier": "b6f44266-5815-48bb-bd0c-dd050c6fe465", + "created": "2023-11-03T21:04:37.548Z", + "userID": "gP03Su7SUndv1bwlW6YnBhtAwSw2", +} + +export default mockMetadataRecord \ No newline at end of file diff --git a/src/__tests__/recordToDataCite.test.js b/src/__tests__/recordToDataCite.test.js new file mode 100644 index 00000000..014723b6 --- /dev/null +++ b/src/__tests__/recordToDataCite.test.js @@ -0,0 +1,19 @@ +import recordToDataCite from './../utils/recordToDataCite' +import licenses from './../utils/licenses'; +import regions from './../regions'; +import mockMetadataRecord from '../__testData__/mockMetadataRecord'; +import expectedDataCiteStructure from '../__testData__/expectedDataCiteStructure'; + +const language = 'en'; +const region = 'hakai'; + +describe('recordToDataCite', () => { + it('should correctly map metadata record to DataCite format', () => { + + const testResult = recordToDataCite(mockMetadataRecord, language, region); + + // Assert that the output matches the expected structure + expect(testResult).toEqual(expectedDataCiteStructure); + + }); +}) \ No newline at end of file diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index 3360b03c..f13cd130 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -4,6 +4,8 @@ import regions from "../regions"; function recordToDataCite(metadata, language, region) { + console.log(JSON.stringify(metadata)); + // Reduce contacts to a list of creators const creators = metadata.contacts ? metadata.contacts.reduce((creatorList, contact) => { let creator; @@ -214,6 +216,8 @@ function recordToDataCite(metadata, language, region) { // Generate URL element mappedDataCiteObject.data.attributes.url = `${regions[region].catalogueURL[language]}dataset/ca-cioos_${metadata.identifier}`; + console.log(JSON.stringify(mappedDataCiteObject)) + return mappedDataCiteObject; } From 5ad06f28befb28e24bda91256f33089f7727ac90 Mon Sep 17 00:00:00 2001 From: Austen Sorochak Date: Fri, 3 Nov 2023 15:31:56 -0700 Subject: [PATCH 8/8] remove console logs --- src/utils/recordToDataCite.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/recordToDataCite.js b/src/utils/recordToDataCite.js index f13cd130..3360b03c 100644 --- a/src/utils/recordToDataCite.js +++ b/src/utils/recordToDataCite.js @@ -4,8 +4,6 @@ import regions from "../regions"; function recordToDataCite(metadata, language, region) { - console.log(JSON.stringify(metadata)); - // Reduce contacts to a list of creators const creators = metadata.contacts ? metadata.contacts.reduce((creatorList, contact) => { let creator; @@ -216,8 +214,6 @@ function recordToDataCite(metadata, language, region) { // Generate URL element mappedDataCiteObject.data.attributes.url = `${regions[region].catalogueURL[language]}dataset/ca-cioos_${metadata.identifier}`; - console.log(JSON.stringify(mappedDataCiteObject)) - return mappedDataCiteObject; }