diff --git a/backend/docs/db/schema.sql b/backend/docs/db/schema.sql index 680c4ec26b..9a568a2279 100644 --- a/backend/docs/db/schema.sql +++ b/backend/docs/db/schema.sql @@ -434,6 +434,7 @@ CREATE TABLE public.seqset_citation_source ( title text NOT NULL, year integer NOT NULL, contributors jsonb NOT NULL, + journal text, CONSTRAINT seqset_citation_source_origin_check CHECK ((origin = ANY (ARRAY['CROSSREF'::text, 'CURATED'::text]))) ); diff --git a/backend/src/main/kotlin/org/loculus/backend/api/SeqSetCitations.kt b/backend/src/main/kotlin/org/loculus/backend/api/SeqSetCitations.kt index 0c68422981..daaae088d5 100644 --- a/backend/src/main/kotlin/org/loculus/backend/api/SeqSetCitations.kt +++ b/backend/src/main/kotlin/org/loculus/backend/api/SeqSetCitations.kt @@ -90,6 +90,11 @@ data class CitationSource( description = "List of contributors to the citation source.", ) val contributors: List, + @Schema( + description = "The journal in which the citation source was published, when applicable.", + example = "Journal of Examples", + ) + val journal: String? = null, ) data class SeqSetCitationSource(val source: CitationSource, val seqSetDOIs: Set = emptySet()) diff --git a/backend/src/main/kotlin/org/loculus/backend/service/crossref/CrossRefService.kt b/backend/src/main/kotlin/org/loculus/backend/service/crossref/CrossRefService.kt index bdf7a37eb0..1c0ba8c146 100644 --- a/backend/src/main/kotlin/org/loculus/backend/service/crossref/CrossRefService.kt +++ b/backend/src/main/kotlin/org/loculus/backend/service/crossref/CrossRefService.kt @@ -166,6 +166,7 @@ class CrossRefService( CitationContributor(givenName, surname) } } + val journal = citationElement.selectFirst("journal_title")?.text()?.takeIf { it.isNotBlank() } SeqSetCitationSource( source = CitationSource( @@ -173,6 +174,7 @@ class CrossRefService( title = title, year = year, contributors = contributors, + journal = journal, ), seqSetDOIs = setOf(seqSetDOI), ) diff --git a/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetCitationsDatabaseService.kt b/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetCitationsDatabaseService.kt index 4cc914fbb1..b6ff5ff0cb 100644 --- a/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetCitationsDatabaseService.kt +++ b/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetCitationsDatabaseService.kt @@ -407,6 +407,7 @@ class SeqSetCitationsDatabaseService( this[SeqSetCitationSourceTable.title] = it.source.title this[SeqSetCitationSourceTable.year] = it.source.year this[SeqSetCitationSourceTable.contributors] = it.source.contributors + this[SeqSetCitationSourceTable.journal] = it.source.journal } .flatMap { result -> val citationSourceId = result[SeqSetCitationSourceTable.citationSourceId] @@ -456,6 +457,7 @@ class SeqSetCitationsDatabaseService( it[SeqSetCitationSourceTable.title], it[SeqSetCitationSourceTable.year], it[SeqSetCitationSourceTable.contributors], + it[SeqSetCitationSourceTable.journal], ), ) } @@ -494,6 +496,7 @@ class SeqSetCitationsDatabaseService( title = first[SeqSetCitationSourceTable.title], year = first[SeqSetCitationSourceTable.year], contributors = first[SeqSetCitationSourceTable.contributors], + journal = first[SeqSetCitationSourceTable.journal], ), seqSets = rows.map { SeqSetCitingSequence( @@ -529,6 +532,7 @@ class SeqSetCitationsDatabaseService( title = first[SeqSetCitationSourceTable.title], year = first[SeqSetCitationSourceTable.year], contributors = first[SeqSetCitationSourceTable.contributors], + journal = first[SeqSetCitationSourceTable.journal], ), seqSets = rows.map { it.toSeqSet() }, origin = first[SeqSetCitationSourceTable.origin], @@ -584,6 +588,7 @@ class SeqSetCitationsDatabaseService( this[SeqSetCitationSourceTable.title] = it.title this[SeqSetCitationSourceTable.year] = it.year this[SeqSetCitationSourceTable.contributors] = it.contributors + this[SeqSetCitationSourceTable.journal] = it.journal } .single()[SeqSetCitationSourceTable.citationSourceId] diff --git a/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetsTables.kt b/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetsTables.kt index 90a1ba68bd..fd3be5830e 100644 --- a/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetsTables.kt +++ b/backend/src/main/kotlin/org/loculus/backend/service/seqsetcitations/SeqSetsTables.kt @@ -44,6 +44,7 @@ object SeqSetCitationSourceTable : Table("seqset_citation_source") { val title = text("title") val year = integer("year") val contributors = jacksonSerializableJsonb>("contributors") + val journal = text("journal").nullable() override val primaryKey = PrimaryKey(citationSourceId) } diff --git a/backend/src/main/resources/db/migration/V1.34__add_journal_to_seqset_citation_source.sql b/backend/src/main/resources/db/migration/V1.34__add_journal_to_seqset_citation_source.sql new file mode 100644 index 0000000000..a250ed7112 --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.34__add_journal_to_seqset_citation_source.sql @@ -0,0 +1 @@ +alter table seqset_citation_source add column journal text; diff --git a/backend/src/test/kotlin/org/loculus/backend/service/crossref/CrossRefServiceTest.kt b/backend/src/test/kotlin/org/loculus/backend/service/crossref/CrossRefServiceTest.kt index 68d99c15bf..11b114a44d 100644 --- a/backend/src/test/kotlin/org/loculus/backend/service/crossref/CrossRefServiceTest.kt +++ b/backend/src/test/kotlin/org/loculus/backend/service/crossref/CrossRefServiceTest.kt @@ -101,6 +101,7 @@ class CrossRefServiceTest( CitationContributor(givenName = "Jane", surname = "Doe"), CitationContributor(givenName = "John", surname = "Smith"), ), + journal = "Journal of Citations", ), seqSetDOIs = setOf("10.1234/seqset-1"), ), diff --git a/website/src/components/AdminDashboard/AddSeqSetCitationForm.tsx b/website/src/components/AdminDashboard/AddSeqSetCitationForm.tsx index 19e49cd5f3..05f7804ba4 100644 --- a/website/src/components/AdminDashboard/AddSeqSetCitationForm.tsx +++ b/website/src/components/AdminDashboard/AddSeqSetCitationForm.tsx @@ -37,6 +37,7 @@ const parseContributor = (line: string) => { /* eslint-disable @typescript-eslint/naming-convention */ type CrossRefWork = { 'title'?: string[]; + 'container-title'?: string[]; 'author'?: { given?: string; family?: string }[]; 'issued'?: { 'date-parts'?: number[][] }; 'published'?: { 'date-parts'?: number[][] }; @@ -60,6 +61,7 @@ export const AddSeqSetCitationForm: FC = ({ clientConfig, accessToken, on const isClient = useClientFlag(); const [sourceDOI, setSourceDOI] = useState(''); const [title, setTitle] = useState(''); + const [journal, setJournal] = useState(''); const [year, setYear] = useState(''); const [contributorsInput, setContributorsInput] = useState(''); const [seqSetAccessionsInput, setSeqSetAccessionsInput] = useState(''); @@ -72,6 +74,7 @@ export const AddSeqSetCitationForm: FC = ({ clientConfig, accessToken, on const resetForm = () => { setSourceDOI(''); setTitle(''); + setJournal(''); setYear(''); setContributorsInput(''); setSeqSetAccessionsInput(''); @@ -96,6 +99,9 @@ export const AddSeqSetCitationForm: FC = ({ clientConfig, accessToken, on if (work.title?.[0] !== undefined) { setTitle(work.title[0]); } + if (work['container-title']?.[0] !== undefined) { + setJournal(work['container-title'][0]); + } const year = extractYear(work); if (year !== undefined) { setYear(String(year)); @@ -146,6 +152,7 @@ export const AddSeqSetCitationForm: FC = ({ clientConfig, accessToken, on title: title.trim(), year: parsedYear, contributors: splitLines(contributorsInput).map(parseContributor), + journal: journal.trim() || undefined, }, seqSetAccessionVersions, }); @@ -226,6 +233,19 @@ export const AddSeqSetCitationForm: FC = ({ clientConfig, accessToken, on disabled={!isClient} /> +
+ + setJournal(e.target.value)} + disabled={!isClient} + /> +