From 3c0ad7ff381bc897b71ea0c4859511c5242cf886 Mon Sep 17 00:00:00 2001 From: karolina-siemieniuk-morawska <55505399+karolina-siemieniuk-morawska@users.noreply.github.com> Date: Wed, 6 Mar 2024 08:46:07 +0100 Subject: [PATCH] change linked_book to linked_books and add pages * ref: cern-sis/issues-inspire#445 * ref: cern-sis/issues-inspire#448 --- .pre-commit-config.yaml | 4 - backend/data/records/literature/2610328.json | 213 ++++++++++++++++++ .../records/marshmallow/literature/ui.py | 58 +++-- .../records/marshmallow/literature/utils.py | 22 ++ .../serializers/json/test_literature.py | 46 +++- .../tests/integration/records/test_utils.py | 57 ++++- docker-compose.yml | 2 +- .../components/ParentRecordInfo.jsx | 41 ---- .../components/ParentRecordInfo.tsx | 46 ++++ .../ReferenceDiffInterface.tsx | 7 +- .../__tests__/ReferenceDiffInterface.test.tsx | 2 +- .../__tests__/ParentRecordInfo.test.jsx | 12 +- .../ParentRecordInfo.test.jsx.snap | 8 +- .../DetailPageContainer.tsx | 15 +- 14 files changed, 438 insertions(+), 95 deletions(-) create mode 100644 backend/data/records/literature/2610328.json delete mode 100644 ui/src/literature/components/ParentRecordInfo.jsx create mode 100644 ui/src/literature/components/ParentRecordInfo.tsx diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d560f78780..b4c4cc579a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,10 +3,6 @@ repos: rev: '22.8.0' hooks: - id: black - - repo: https://github.com/pre-commit/mirrors-prettier - rev: 'v2.7.1' - hooks: - - id: prettier - repo: https://github.com/pycqa/isort rev: '5.12.0' hooks: diff --git a/backend/data/records/literature/2610328.json b/backend/data/records/literature/2610328.json new file mode 100644 index 0000000000..70c6d23f9f --- /dev/null +++ b/backend/data/records/literature/2610328.json @@ -0,0 +1,213 @@ +{ + "_collections": [ + "Literature" + ], + "publication_info": [ + { + "year": 1938, + "page_end": "334", + "page_start": "333", + "journal_issue": "3564", + "journal_title": "Nature", + "journal_record": { + "$ref": "https://inspirehep.net/api/journals/1214565" + }, + "journal_volume": "141", + "curated_relation": true + }, + { + "year": 1937, + "page_end": "306", + "page_start": "305", + "journal_issue": "6", + "journal_title": "Compt.Rend.Acad.Sci.URSS", + "journal_record": { + "$ref": "https://inspirehep.net/api/journals/1213104" + }, + "journal_volume": "17", + "curated_relation": true + }, + { + "year": 1937, + "page_end": "302", + "page_start": "301", + "journal_issue": "6", + "journal_title": "Dokl.Akad.Nauk SSSR", + "journal_record": { + "$ref": "https://inspirehep.net/api/journals/1214770" + }, + "journal_volume": "17", + "curated_relation": true + }, + { + "year": 1965, + "page_end": "186", + "page_start": "185", + "parent_isbn": "9780080105864", + "parent_record": { + "$ref": "https://inspirehep.net/api/literature/1787272" + }, + "curated_relation": true + }, + { + "year": 1969, + "page_end": "226", + "page_start": "224", + "parent_record": { + "$ref": "https://inspirehep.net/api/literature/1649231" + }, + "curated_relation": true + } + ], + "core": false, + "dois": [ + { + "value": "10.1038/141333b0" + }, + { + "value": "10.1016/b978-0-08-010586-4.50032-8" + } + ], + "titles": [ + { + "title": "On the origin of stellar energy", + "source": "submitter" + } + ], + "$schema": "https://inspirehep.net/schemas/records/hep.json", + "authors": [ + { + "ids": [ + { + "value": "L.D.Landau.1", + "schema": "INSPIRE BAI" + }, + { + "value": "INSPIRE-00147020", + "schema": "INSPIRE ID" + }, + { + "value": "HEPNAMES-419974", + "schema": "SPIRES" + } + ], + "uuid": "82a5ac21-af55-4b6b-a09b-1f3630844d61", + "record": { + "$ref": "https://inspirehep.net/api/authors/1019139" + }, + "full_name": "Landau, Lev Davidovich", + "signature_block": "LANDl", + "curated_relation": true, + "alternative_names": [ + "Ландау, Л.Д." + ] + } + ], + "curated": true, + "texkeys": [ + "Landau:1937fjr", + "Landau:1965ujg" + ], + "citeable": true, + "refereed": true, + "abstracts": [ + { + "value": "It is well known that matter consists of nuclei and electrons. Nevertheless it can be shown that in bodies of very large mass, this usual 'electronic' state of matter can become unstable. The reason for this lies in the fact that the 'electronic' state of matter does not lead to extremely great densities, because at such densities electrons form a Fermi gas having an immense pressure. On the other hand, it is easy to see that matter can go into another state which is much more compressible—the state where all the nuclei and electrons have combined to form neutrons.1 Even if we assume that neutrons repel each other, this repulsion can become appreciable only at densities of the order of magnitude of nuclear densities, that is, $10^{14}$ gm/cm$^3$, and the pressure of a Fermi gas consisting of neutrons is much less than that of an electronic gas of the same density, because of the greater mass of the neutrons." + } + ], + "references": [ + { + "raw_refs": [ + { + "value": "1. Cf.", + "schema": "text" + } + ], + "reference": { + "misc": [ + "Cf." + ], + "label": "1" + } + }, + { + "raw_refs": [ + { + "value": "Hund, F., Erg. d. exakten Natwis. 15, 189 (1936).", + "schema": "text" + } + ], + "reference": { + "label": "1", + "authors": [ + { + "full_name": "Hund, F." + } + ], + "publication_info": { + "year": 1936, + "artid": "189", + "page_start": "189", + "journal_title": "Ergeb.Exakt.Naturwiss.", + "journal_volume": "15" + } + }, + "curated_relation": true + }, + { + "record": { + "$ref": "https://inspirehep.net/api/literature/2609859" + }, + "raw_refs": [ + { + "value": "2. Landau, L., Sov. Phys., 1, 285 (1932).", + "schema": "text" + } + ], + "reference": { + "label": "2", + "authors": [ + { + "full_name": "Landau, L." + } + ], + "publication_info": { + "year": 1932, + "artid": "285", + "page_start": "285", + "journal_title": "Phys.Z.Sowjetunion", + "journal_volume": "1" + } + }, + "curated_relation": true + } + ], + "public_notes": [ + { + "value": "References drawn from Nature 141(1938)333. Reprinted (in Russian) in: Л. Д. Ландау [L. D. Landau]: Собрание трудов [Sobranie trudov], Vol. 1. Наука [Nauka], Moscow, 1969, item 26, pp. 224-226 (available online at the following site of the Russian Academy of Sciences: http://www.e-heritage.ru/Book/10079744 ). Reprint of the English translation [Nature 141(1938)333] in: D. ter Haar (Ed.): Collected Papers of L D Landau. Edited and with an introduction by D ter Haar. Pergamon Press, Oxford, 1965, item 27, pp. 185-186 (ISBN-13: 978-0-08-010586-4)." + } + ], + "document_type": [ + "article", + "book chapter" + ], + "control_number": 2610328, + "number_of_pages": 2, + "inspire_categories": [ + { + "term": "Phenomenology-HEP" + }, + { + "term": "Astrophysics" + }, + { + "term": "Theory-Nucl" + } + ], + "title_translations": [ + { + "title": "Об источниках звездной энергии [Ob istochnikakh zvezdnoĭ ènergii]", + "language": "ru" + } + ] + } diff --git a/backend/inspirehep/records/marshmallow/literature/ui.py b/backend/inspirehep/records/marshmallow/literature/ui.py index 3049c27d8c..4213e9f36c 100644 --- a/backend/inspirehep/records/marshmallow/literature/ui.py +++ b/backend/inspirehep/records/marshmallow/literature/ui.py @@ -6,7 +6,8 @@ # the terms of the MIT License; see LICENSE file for more details. import orjson -from flask import current_app, request, url_for +from flask import current_app, request +from inspire_dojson.utils import get_record_ref from inspire_utils.date import format_date from inspire_utils.record import get_value, get_values_for_schema from marshmallow import fields, missing, pre_dump @@ -17,11 +18,14 @@ ) from inspirehep.assign.utils import can_claim, is_assign_view_enabled from inspirehep.files.api import current_s3_instance -from inspirehep.pidstore.api import PidStoreBase from inspirehep.records.marshmallow.common.mixins import ( CanEditByCollectionPermissionMixin, ) -from inspirehep.records.marshmallow.literature.utils import get_parent_record +from inspirehep.records.marshmallow.literature.utils import ( + get_authors_without_emails, + get_pages, + get_parent_records, +) from inspirehep.records.utils import get_literature_earliest_date from ..base import EnvelopeSchema @@ -39,7 +43,6 @@ PublicationInfoItemSchemaV1, ThesisInfoSchemaV1, ) -from .utils import get_authors_without_emails from .pdg_identifiers import PDG_IDS_TO_DESCRIPTION_MAPPING DATASET_SCHEMA_TO_URL_PREFIX_MAP = { @@ -102,8 +105,8 @@ class Meta: ) fulltext_links = fields.Method("get_fulltext_links", dump_only=True) isbns = fields.List(fields.Nested(IsbnSchemaV1, dump_only=True)) - linked_book = fields.Method( - "get_linked_book", dump_only=True, attribute="publication_info" + linked_books = fields.Method( + "get_linked_books", dump_only=True, attribute="publication_info" ) number_of_authors = fields.Method("get_number_of_authors") number_of_references = fields.Method("get_number_of_references") @@ -185,18 +188,26 @@ def get_number_of_references(self, data): references = data.get("references") return self.get_len_or_missing(references) - def get_linked_book(self, data): - parent = get_parent_record(data) - if parent and "titles" in parent and "control_number" in parent: - endpoint = PidStoreBase.get_endpoint_from_pid_type( - PidStoreBase.get_pid_type_from_schema(data["$schema"]) - ) - endpoint_item = f"invenio_records_rest.{endpoint}_item" - ref = get_value(parent, "self.$ref") or url_for( - endpoint_item, pid_value=parent["control_number"], _external=True + def get_linked_books(self, data): + parents = get_parent_records(data) + pages = get_pages(data) + + records = [ + { + **parent["titles"][0], + "record": get_record_ref(parent["control_number"], "literature"), + } + for parent in parents + if parent and "titles" in parent and "control_number" in parent + ] + merged_list = [ + {"page_start": start, "page_end": end, **record} + for start, end, record in zip( + pages["page_start"], pages["page_end"], records ) - return {**parent["titles"][0], "record": {"$ref": ref}} - return None + ] + + return merged_list @staticmethod def get_len_or_missing(maybe_none_list): @@ -268,10 +279,15 @@ def get_pdg_keywords(self, data): pdg_keywords = [] for keyword_entry in keywords: - if keyword_entry.get('schema') != 'PDG': + if keyword_entry.get("schema") != "PDG": continue - pdg_identifier = keyword_entry['value'] - pdg_keywords.append({'value': pdg_identifier, 'description': PDG_IDS_TO_DESCRIPTION_MAPPING[pdg_identifier]}) + pdg_identifier = keyword_entry["value"] + pdg_keywords.append( + { + "value": pdg_identifier, + "description": PDG_IDS_TO_DESCRIPTION_MAPPING[pdg_identifier], + } + ) return pdg_keywords @@ -280,7 +296,7 @@ def get_keywords(self, data): keywords_without_pdg = [] for keyword_entry in keywords: - if keyword_entry.get('schema') != 'PDG': + if keyword_entry.get("schema") != "PDG": keywords_without_pdg.append(keyword_entry) return keywords_without_pdg diff --git a/backend/inspirehep/records/marshmallow/literature/utils.py b/backend/inspirehep/records/marshmallow/literature/utils.py index 97e40a2926..992b08fdde 100644 --- a/backend/inspirehep/records/marshmallow/literature/utils.py +++ b/backend/inspirehep/records/marshmallow/literature/utils.py @@ -20,6 +20,28 @@ MATH_EXPRESSION_REGEX = re.compile(r"((? - Part of - - {parentRecord.get('title')} - {parentRecord.has('subtitle') && ( - : {parentRecord.get('subtitle')} - )} - - {pageStart && pageEnd && ( - - , {pageStart}-{pageEnd} - - )} - - ); -} - -ParentRecordInfo.propTypes = { - parentRecord: PropTypes.instanceOf(Map).isRequired, -}; - -export default ParentRecordInfo; diff --git a/ui/src/literature/components/ParentRecordInfo.tsx b/ui/src/literature/components/ParentRecordInfo.tsx new file mode 100644 index 0000000000..cc8684465d --- /dev/null +++ b/ui/src/literature/components/ParentRecordInfo.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Map } from 'immutable'; +import { Link } from 'react-router-dom'; + +import { getRecordIdFromRef } from '../../common/utils'; +import { LITERATURE } from '../../common/routes'; + +interface ParentRecordInfoProps { + parentRecord: Map; +} + +const renderBook = (data: Map): JSX.Element[] => + data + .entrySeq() + .map(([key, item]: [string, Map], index: number) => ( + + + {item.get('title')} + {item.get('subtitle') && : {item.get('subtitle')}} + + {(item.has('page_start') || item.has('page_end')) && ( + + , {item.get('page_start') || ''} + {item.get('page_start') && item.get('page_end') ? '-' : ''} + {item.get('page_end') || ''} + + )} + {index < data.size - 1 && , } + + )) + .toArray(); + +const ParentRecordInfo: React.FC = ({ + parentRecord, +}) => ( +
+ Part of + {renderBook(parentRecord)} +
+); + +export default ParentRecordInfo; diff --git a/ui/src/literature/components/ReferenceDiffInterface/ReferenceDiffInterface.tsx b/ui/src/literature/components/ReferenceDiffInterface/ReferenceDiffInterface.tsx index b0237dc7ee..94b35f3b74 100644 --- a/ui/src/literature/components/ReferenceDiffInterface/ReferenceDiffInterface.tsx +++ b/ui/src/literature/components/ReferenceDiffInterface/ReferenceDiffInterface.tsx @@ -86,7 +86,7 @@ function ReferenceDiffInterface({ const urls = metadata.get('urls'); const collaborations = metadata.get('collaborations'); const collaborationsWithSuffix = metadata.get('collaborations_with_suffix'); - const linkedBook = metadata.get('linked_book'); + const linkedBooks = metadata.get('linked_books'); const bookSeries = metadata.get('book_series'); const PDGkeywords = metadata.get('pdg_keywords'); const authorCount = metadata.get('author_count'); @@ -214,10 +214,9 @@ function ReferenceDiffInterface({ page="Literature detail" /> - {linkedBook && ( + {linkedBooks && ( )} {bookSeries && } diff --git a/ui/src/literature/components/ReferenceDiffInterface/__tests__/ReferenceDiffInterface.test.tsx b/ui/src/literature/components/ReferenceDiffInterface/__tests__/ReferenceDiffInterface.test.tsx index 5f7b3e30e4..2431f1f854 100644 --- a/ui/src/literature/components/ReferenceDiffInterface/__tests__/ReferenceDiffInterface.test.tsx +++ b/ui/src/literature/components/ReferenceDiffInterface/__tests__/ReferenceDiffInterface.test.tsx @@ -30,7 +30,7 @@ describe('ReferenceDiffInterface', () => { urls: null, collaborations: [{ value: 'CMS' }], collaborations_with_suffix: [{ value: 'CMS' }], - linked_book: null, + linked_books: null, book_series: null, pdg_keywords: null, author_count: 1, diff --git a/ui/src/literature/components/__tests__/ParentRecordInfo.test.jsx b/ui/src/literature/components/__tests__/ParentRecordInfo.test.jsx index 6b194a9c03..e8ed57cdc1 100644 --- a/ui/src/literature/components/__tests__/ParentRecordInfo.test.jsx +++ b/ui/src/literature/components/__tests__/ParentRecordInfo.test.jsx @@ -6,20 +6,22 @@ import ParentRecordInfo from '../ParentRecordInfo'; describe('ParentRecordInfo', () => { it('renders with parent record', () => { - const parentRecord = fromJS({ + const parentRecord = fromJS([{ title: 'A title of book', record: { $ref: 'http://localhost:5000/api/literature/1234' }, - }); + }]); const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); - it('renders with parent record', () => { - const parentRecord = fromJS({ + it('renders with subtitle and pages in parent record', () => { + const parentRecord = fromJS([{ title: 'A title of book', subtitle: 'A subtitle', + page_start: '1', + page_end: '10', record: { $ref: 'http://localhost:5000/api/literature/1234' }, - }); + }]); const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); diff --git a/ui/src/literature/components/__tests__/__snapshots__/ParentRecordInfo.test.jsx.snap b/ui/src/literature/components/__tests__/__snapshots__/ParentRecordInfo.test.jsx.snap index 39727473f1..1f167084f5 100644 --- a/ui/src/literature/components/__tests__/__snapshots__/ParentRecordInfo.test.jsx.snap +++ b/ui/src/literature/components/__tests__/__snapshots__/ParentRecordInfo.test.jsx.snap @@ -13,7 +13,7 @@ exports[`ParentRecordInfo renders with parent record 1`] = ` `; -exports[`ParentRecordInfo renders with parent record 2`] = ` +exports[`ParentRecordInfo renders with subtitle and pages in parent record 1`] = `
Part of @@ -27,5 +27,11 @@ exports[`ParentRecordInfo renders with parent record 2`] = ` A subtitle + + , + 1 + - + 10 +
`; diff --git a/ui/src/literature/containers/DetailPageContainer/DetailPageContainer.tsx b/ui/src/literature/containers/DetailPageContainer/DetailPageContainer.tsx index 7a3467a7a9..eacee74241 100644 --- a/ui/src/literature/containers/DetailPageContainer/DetailPageContainer.tsx +++ b/ui/src/literature/containers/DetailPageContainer/DetailPageContainer.tsx @@ -47,7 +47,10 @@ import ReferenceSearchLinkAction from '../../../common/components/ReferenceSearc import { getPapersQueryString } from '../../utils'; import ParentRecordInfo from '../../components/ParentRecordInfo'; import BookSeriesInfoList from '../../components/BookSeriesInfoList'; -import { CURATE_REFERENCE_NS, LITERATURE_SEMINARS_NS } from '../../../search/constants'; +import { + CURATE_REFERENCE_NS, + LITERATURE_SEMINARS_NS, +} from '../../../search/constants'; import LiteratureSeminars from '../../components/LiteratureSeminars'; import { newSearch, searchBaseQueriesUpdate } from '../../../actions/search'; import ImprintInfo from '../../components/ImprintInfo'; @@ -103,7 +106,8 @@ function DetailPage({ const urls = metadata.get('urls'); const collaborations = metadata.get('collaborations'); const collaborationsWithSuffix = metadata.get('collaborations_with_suffix'); - const linkedBook = metadata.get('linked_book'); + const linkedBooks = metadata.get('linked_books'); + const bookSeries = metadata.get('book_series'); const hiddenCollection = metadata.get('is_collection_hidden'); const keywords = metadata.get('keywords'); @@ -294,11 +298,8 @@ function DetailPage({ page="Literature detail" /> - {linkedBook && ( - + {linkedBooks && ( + )} {bookSeries && } {publicationInfoWithTitle &&