From b30cbdf8dc0d064d3f3df5758a6083a6384fead2 Mon Sep 17 00:00:00 2001 From: karolina-siemieniuk-morawska Date: Tue, 13 Feb 2024 13:20:59 +0100 Subject: [PATCH] ui: add conference contribution link to detail page * ref: cern-sis/issues-inspire#443 --- .../components/ConferenceContributionLink.tsx | 37 +++++ .../components/ConferenceDates.jsx | 68 -------- .../components/ConferenceDates.tsx | 78 +++++++++ .../conferences/components/ConferenceItem.jsx | 114 ------------- .../conferences/components/ConferenceItem.tsx | 102 ++++++++++++ .../ConferenceContributionLink.test.jsx | 23 +++ .../ConferenceContributions.test.jsx | 15 +- .../__tests__/ConferenceDates.test.jsx | 41 +++-- .../ConferenceContributionLink.test.jsx.snap | 49 ++++++ .../ConferenceContributions.test.jsx.snap | 150 ++++++++++++++++-- .../ConferenceDates.test.jsx.snap | 62 ++++++-- .../ConferenceItem.test.jsx.snap | 28 +--- .../containers/DetailPageContainer.jsx | 8 + .../__tests__/CurateReferenceDrawer.test.tsx | 4 +- .../__tests__/SettingsContainer.test.tsx | 2 +- 15 files changed, 524 insertions(+), 257 deletions(-) create mode 100644 ui/src/conferences/components/ConferenceContributionLink.tsx delete mode 100644 ui/src/conferences/components/ConferenceDates.jsx create mode 100644 ui/src/conferences/components/ConferenceDates.tsx delete mode 100644 ui/src/conferences/components/ConferenceItem.jsx create mode 100644 ui/src/conferences/components/ConferenceItem.tsx create mode 100644 ui/src/conferences/components/__tests__/ConferenceContributionLink.test.jsx create mode 100644 ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributionLink.test.jsx.snap diff --git a/ui/src/conferences/components/ConferenceContributionLink.tsx b/ui/src/conferences/components/ConferenceContributionLink.tsx new file mode 100644 index 0000000000..3eb927e495 --- /dev/null +++ b/ui/src/conferences/components/ConferenceContributionLink.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { LoginOutlined } from '@ant-design/icons'; +import { Link } from 'react-router-dom'; + +import IconText from '../../common/components/IconText'; +import UserAction from '../../common/components/UserAction'; +import { LITERATURE } from '../../common/routes'; +import { pluralizeUnlessSingle } from '../../common/utils'; +import { getContributionsQueryString } from '../utils'; + +const ConferenceContributionLink = ({ + recordId, + contributionsCount, +}: { + recordId: string; + contributionsCount: number; +}) => { + return ( + + + } + /> + + + ); +}; + +export default ConferenceContributionLink; diff --git a/ui/src/conferences/components/ConferenceDates.jsx b/ui/src/conferences/components/ConferenceDates.jsx deleted file mode 100644 index af9d60c8c9..0000000000 --- a/ui/src/conferences/components/ConferenceDates.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import PropTypes from 'prop-types'; -import moment from 'moment'; -import { hasDayMonthAndYear, hasMonthAndYear } from '../../common/utils'; - -function getDisplayFormatForDateString(date) { - if (hasDayMonthAndYear(date)) { - return 'D MMMM YYYY'; - } - - if (hasMonthAndYear(date)) { - return 'MMMM YYYY'; - } - - return 'YYYY'; -} - -function ConferenceDates({ openingDate, closingDate }) { - if (!openingDate) { - return null; - } - - const displayFormat = getDisplayFormatForDateString(openingDate); - const openingMoment = moment(openingDate); - if (!closingDate) { - return openingMoment.format(displayFormat); - } - - const closingMoment = moment(closingDate); - - if (openingMoment.isSame(closingMoment)) { - return openingMoment.format(displayFormat); - } - - if (openingMoment.isSame(closingMoment, 'month')) { - if (hasDayMonthAndYear(openingDate)) { - return `${openingMoment.format('D')}-${closingMoment.format( - displayFormat - )}`; - } - return openingMoment.format(displayFormat); - } - - if (openingMoment.isSame(closingMoment, 'year')) { - if (hasDayMonthAndYear(openingDate)) { - return `${openingMoment.format('D MMMM')}-${closingMoment.format( - displayFormat - )}`; - } - - if (hasMonthAndYear(openingDate)) { - return `${openingMoment.format('MMMM')}-${closingMoment.format( - displayFormat - )}`; - } - return openingMoment.format(displayFormat); - } - - return `${openingMoment.format(displayFormat)}-${closingMoment.format( - displayFormat - )}`; -} - -ConferenceDates.propTypes = { - openingDate: PropTypes.string.isRequired, - closingDate: PropTypes.string, -}; - -export default ConferenceDates; diff --git a/ui/src/conferences/components/ConferenceDates.tsx b/ui/src/conferences/components/ConferenceDates.tsx new file mode 100644 index 0000000000..adf078d3f8 --- /dev/null +++ b/ui/src/conferences/components/ConferenceDates.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import moment from 'moment'; + +import { hasDayMonthAndYear, hasMonthAndYear } from '../../common/utils'; + +function getDisplayFormatForDateString(date: any) { + if (hasDayMonthAndYear(date)) { + return 'D MMMM YYYY'; + } + + if (hasMonthAndYear(date)) { + return 'MMMM YYYY'; + } + + return 'YYYY'; +} + +function ConferenceDates({ + openingDate, + closingDate, +}: { + openingDate: string; + closingDate?: string; +}) { + if (!openingDate) { + return null; + } + + const displayFormat = getDisplayFormatForDateString(openingDate); + const openingMoment = moment(openingDate); + if (!closingDate) { + return <>{openingMoment.format(displayFormat)}; + } + + const closingMoment = moment(closingDate); + + if (openingMoment.isSame(closingMoment)) { + return <>{openingMoment.format(displayFormat)}; + } + + if (openingMoment.isSame(closingMoment, 'month')) { + if (hasDayMonthAndYear(openingDate)) { + return ( + <>{`${openingMoment.format('D')}-${closingMoment.format( + displayFormat + )}`} + ); + } + return <>{openingMoment.format(displayFormat)}; + } + + if (openingMoment.isSame(closingMoment, 'year')) { + if (hasDayMonthAndYear(openingDate)) { + return ( + <>{`${openingMoment.format('D MMMM')}-${closingMoment.format( + displayFormat + )}`} + ); + } + + if (hasMonthAndYear(openingDate)) { + return ( + <>{`${openingMoment.format('MMMM')}-${closingMoment.format( + displayFormat + )}`} + ); + } + return <>{openingMoment.format(displayFormat)}; + } + + return ( + <>{`${openingMoment.format(displayFormat)}-${closingMoment.format( + displayFormat + )}`} + ); +} + +export default ConferenceDates; diff --git a/ui/src/conferences/components/ConferenceItem.jsx b/ui/src/conferences/components/ConferenceItem.jsx deleted file mode 100644 index d1ffe8bf0e..0000000000 --- a/ui/src/conferences/components/ConferenceItem.jsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { Component } from 'react'; -import { Link } from 'react-router-dom'; -import PropTypes from 'prop-types'; -import { Map } from 'immutable'; -import { LoginOutlined } from '@ant-design/icons'; - -import { Row, Col } from 'antd'; -import EditRecordAction from '../../common/components/EditRecordAction'; -import ResultItem from '../../common/components/ResultItem'; -import { CONFERENCES, LITERATURE } from '../../common/routes'; -import ConferenceDates from './ConferenceDates'; -import AddressList from '../../common/components/AddressList'; -import InspireCategoryList from './InspireCategoryList'; -import ProceedingsAction from './ProceedingsAction'; -import { pluralizeUnlessSingle } from '../../common/utils'; -import IconText from '../../common/components/IconText'; -import UserAction from '../../common/components/UserAction'; -import { getContributionsQueryString } from '../utils'; -import EventTitle from '../../common/components/EventTitle'; -import UrlsAction from '../../literature/components/UrlsAction'; - -class ConferenceItem extends Component { - render() { - const { metadata, openDetailInNewTab } = this.props; - - const title = metadata.getIn(['titles', 0]); - const acronym = metadata.getIn(['acronyms', 0]); - const openingDate = metadata.get('opening_date'); - const closingDate = metadata.get('closing_date'); - const addresses = metadata.get('addresses'); - const cnum = metadata.get('cnum'); - const recordId = metadata.get('control_number'); - const canEdit = metadata.get('can_edit', false); - const inspireCategories = metadata.get('inspire_categories'); - const urls = metadata.get('urls'); - const proceedings = metadata.get('proceedings'); - const contributionsCount = metadata.get('number_of_contributions', 0); - - return ( - - {urls && } - {proceedings && } - {canEdit && ( - - )} - - } - rightActions={ - contributionsCount !== 0 && ( - - - } - /> - - - ) - } - > - - - - - - - - - - - {addresses && ( - <> - {'. '} - - - )} - {cnum && ` (${cnum})`} - - - - - - - - - ); - } -} - -ConferenceItem.propTypes = { - metadata: PropTypes.instanceOf(Map).isRequired, - openDetailInNewTab: PropTypes.bool, -}; - -export default ConferenceItem; diff --git a/ui/src/conferences/components/ConferenceItem.tsx b/ui/src/conferences/components/ConferenceItem.tsx new file mode 100644 index 0000000000..b4d3e18d81 --- /dev/null +++ b/ui/src/conferences/components/ConferenceItem.tsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Map } from 'immutable'; + +import { Row, Col } from 'antd'; +import EditRecordAction from '../../common/components/EditRecordAction'; +import ResultItem from '../../common/components/ResultItem'; +import { CONFERENCES } from '../../common/routes'; +import ConferenceDates from './ConferenceDates'; +import AddressList from '../../common/components/AddressList'; +import InspireCategoryList from './InspireCategoryList'; +import ProceedingsAction from './ProceedingsAction'; +import EventTitle from '../../common/components/EventTitle'; +import UrlsAction from '../../literature/components/UrlsAction'; +import ConferenceContributionLink from './ConferenceContributionLink'; + +const ConferenceItem = ({ + metadata, + openDetailInNewTab, +}: { + metadata: Map; + openDetailInNewTab: boolean; +}) => { + const title = metadata.getIn(['titles', 0]); + const acronym = metadata.getIn(['acronyms', 0]); + const openingDate = metadata.get('opening_date'); + const closingDate = metadata.get('closing_date'); + const addresses = metadata.get('addresses'); + const cnum = metadata.get('cnum'); + const recordId = metadata.get('control_number'); + const canEdit = metadata.get('can_edit', false); + const inspireCategories = metadata.get('inspire_categories'); + const urls = metadata.get('urls'); + const proceedings = metadata.get('proceedings'); + const contributionsCount = metadata.get('number_of_contributions', 0); + + return ( + + {urls && ( + + )} + {proceedings && } + {canEdit && ( + + )} + + } + rightActions={ + contributionsCount !== 0 && ( + + ) + } + > + + + + + + + + + + + {addresses && ( + <> + {'. '} + + + )} + {cnum && ` (${cnum})`} + + + + + + + + + ); +}; + +export default ConferenceItem; diff --git a/ui/src/conferences/components/__tests__/ConferenceContributionLink.test.jsx b/ui/src/conferences/components/__tests__/ConferenceContributionLink.test.jsx new file mode 100644 index 0000000000..f922b5d5c2 --- /dev/null +++ b/ui/src/conferences/components/__tests__/ConferenceContributionLink.test.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { MemoryRouter } from 'react-router-dom'; + +import ConferenceContributionLink from '../ConferenceContributionLink'; +import { getStore } from '../../../fixtures/store'; + +describe('ConferenceContributionLink', () => { + it('renders ConferenceContributionLink', () => { + const { asFragment } = render( + + + + + + ); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/ui/src/conferences/components/__tests__/ConferenceContributions.test.jsx b/ui/src/conferences/components/__tests__/ConferenceContributions.test.jsx index 0b8cf4f3b8..5916ad0e42 100644 --- a/ui/src/conferences/components/__tests__/ConferenceContributions.test.jsx +++ b/ui/src/conferences/components/__tests__/ConferenceContributions.test.jsx @@ -1,13 +1,20 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { MemoryRouter } from 'react-router-dom'; import ConferenceContributions from '../ConferenceContributions'; +import { getStore } from '../../../fixtures/store'; describe('ConferenceContributions', () => { it('renders', () => { - const wrapper = shallow( - + const { container } = render( + + + + + ); - expect(wrapper).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/src/conferences/components/__tests__/ConferenceDates.test.jsx b/ui/src/conferences/components/__tests__/ConferenceDates.test.jsx index 4061f7db8f..fb4f838b05 100644 --- a/ui/src/conferences/components/__tests__/ConferenceDates.test.jsx +++ b/ui/src/conferences/components/__tests__/ConferenceDates.test.jsx @@ -1,62 +1,61 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; import ConferenceDates from '../ConferenceDates'; describe('ConferenceDates', () => { - it('renders only opening date ', () => { - const opening = '2019-05-12' - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const opening = '2019-05-12'; + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders only opening date with missing day', () => { - const opening = '2019-05' - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const opening = '2019-05'; + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders only of the dates if opening and closing are same', () => { const opening = '2019-05-02'; const closing = '2019-05-02'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders when opening and closing on different dates of the same month', () => { const opening = '2019-05-02'; const closing = '2019-05-05'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); - it('renders when opening and closing in different months of the same year', () => { const opening = '2019-04-29'; const closing = '2019-05-05'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders when opening and closing in different months of the same year and day is missing', () => { const opening = '2019-04'; const closing = '2019-07'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders when opening and closing has only (same) year', () => { const opening = '2019'; const closing = '2019'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); it('renders when opening and closing is completely different', () => { const opening = '2019-12-30'; const closing = '2020-01-05'; - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + const { container } = render(); + expect(container).toMatchSnapshot(); }); }); diff --git a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributionLink.test.jsx.snap b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributionLink.test.jsx.snap new file mode 100644 index 0000000000..67087a970d --- /dev/null +++ b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributionLink.test.jsx.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConferenceContributionLink renders ConferenceContributionLink 1`] = ` + + + + + + + + + 25 contributions + + + + + +`; diff --git a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributions.test.jsx.snap b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributions.test.jsx.snap index 7997899e57..5734efa69f 100644 --- a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributions.test.jsx.snap +++ b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceContributions.test.jsx.snap @@ -1,15 +1,143 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ConferenceContributions renders 1`] = ` - +
+
+
+
+
+
+ + + 0 + + results + + + +
+
+ + + Citation Summary + + + +
+
+
+
+
+
+
+
+
+
`; diff --git a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceDates.test.jsx.snap b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceDates.test.jsx.snap index f6dcf011ad..d613615b2d 100644 --- a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceDates.test.jsx.snap +++ b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceDates.test.jsx.snap @@ -1,17 +1,49 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ConferenceDates renders only of the dates if opening and closing are same 1`] = `"2 May 2019"`; - -exports[`ConferenceDates renders only opening date 1`] = `"12 May 2019"`; - -exports[`ConferenceDates renders only opening date with missing day 1`] = `"May 2019"`; - -exports[`ConferenceDates renders when opening and closing has only (same) year 1`] = `"2019"`; - -exports[`ConferenceDates renders when opening and closing in different months of the same year 1`] = `"29 April-5 May 2019"`; - -exports[`ConferenceDates renders when opening and closing in different months of the same year and day is missing 1`] = `"April-July 2019"`; - -exports[`ConferenceDates renders when opening and closing is completely different 1`] = `"30 December 2019-5 January 2020"`; - -exports[`ConferenceDates renders when opening and closing on different dates of the same month 1`] = `"2-5 May 2019"`; +exports[`ConferenceDates renders only of the dates if opening and closing are same 1`] = ` +
+ 2 May 2019 +
+`; + +exports[`ConferenceDates renders only opening date 1`] = ` +
+ 12 May 2019 +
+`; + +exports[`ConferenceDates renders only opening date with missing day 1`] = ` +
+ May 2019 +
+`; + +exports[`ConferenceDates renders when opening and closing has only (same) year 1`] = ` +
+ 2019 +
+`; + +exports[`ConferenceDates renders when opening and closing in different months of the same year 1`] = ` +
+ 29 April-5 May 2019 +
+`; + +exports[`ConferenceDates renders when opening and closing in different months of the same year and day is missing 1`] = ` +
+ April-July 2019 +
+`; + +exports[`ConferenceDates renders when opening and closing is completely different 1`] = ` +
+ 30 December 2019-5 January 2020 +
+`; + +exports[`ConferenceDates renders when opening and closing on different dates of the same month 1`] = ` +
+ 2-5 May 2019 +
+`; diff --git a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceItem.test.jsx.snap b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceItem.test.jsx.snap index 5bb7a6090f..891245f30c 100644 --- a/ui/src/conferences/components/__tests__/__snapshots__/ConferenceItem.test.jsx.snap +++ b/ui/src/conferences/components/__tests__/__snapshots__/ConferenceItem.test.jsx.snap @@ -39,21 +39,13 @@ exports[`ConferenceItem renders with all props set 1`] = ` } rightActions={ - - - } - text="3 contributions" - /> - - + } > - + @@ -118,13 +109,10 @@ exports[`ConferenceItem renders with only needed props 1`] = ` leftActions={} rightActions={false} > - + - + diff --git a/ui/src/conferences/containers/DetailPageContainer.jsx b/ui/src/conferences/containers/DetailPageContainer.jsx index bad62be890..af8afd0fdb 100644 --- a/ui/src/conferences/containers/DetailPageContainer.jsx +++ b/ui/src/conferences/containers/DetailPageContainer.jsx @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import { Map } from 'immutable'; import { Row, Col } from 'antd'; + import DocumentHead from '../../common/components/DocumentHead'; import ConferenceDates from '../components/ConferenceDates'; import fetchConference from '../../actions/conferences'; @@ -27,6 +28,7 @@ import { CONFERENCES_PID_TYPE } from '../../common/constants'; import UrlsAction from '../../literature/components/UrlsAction'; import { isSuperUser } from '../../common/authorization'; import { APIButton } from '../../common/components/APIButton'; +import ConferenceContributionLink from '../components/ConferenceContributionLink'; function DetailPage({ record, isSuperUserLoggedIn }) { const metadata = record.get('metadata'); @@ -47,6 +49,7 @@ function DetailPage({ record, isSuperUserLoggedIn }) { const proceedings = metadata.get('proceedings'); const canEdit = metadata.get('can_edit', false); const deleted = metadata.get('deleted', false); + const contributionsCount = metadata.get('number_of_contributions', 0); const metaDescription = makeCompliantMetaDescription(description); @@ -57,6 +60,11 @@ function DetailPage({ record, isSuperUserLoggedIn }) { + ) + } leftActions={ <> {urls && } diff --git a/ui/src/literature/components/CurateReferenceDrawer/__tests__/CurateReferenceDrawer.test.tsx b/ui/src/literature/components/CurateReferenceDrawer/__tests__/CurateReferenceDrawer.test.tsx index 1c9d4ac08c..a51e9a6d53 100644 --- a/ui/src/literature/components/CurateReferenceDrawer/__tests__/CurateReferenceDrawer.test.tsx +++ b/ui/src/literature/components/CurateReferenceDrawer/__tests__/CurateReferenceDrawer.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { Map, fromJS, List } from 'immutable'; +import { render, screen } from '@testing-library/react'; +import { Map, fromJS } from 'immutable'; import { Provider } from 'react-redux'; import { MemoryRouter } from 'react-router-dom'; diff --git a/ui/src/settings/containers/__tests__/SettingsContainer.test.tsx b/ui/src/settings/containers/__tests__/SettingsContainer.test.tsx index 562063528d..6b954df267 100644 --- a/ui/src/settings/containers/__tests__/SettingsContainer.test.tsx +++ b/ui/src/settings/containers/__tests__/SettingsContainer.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, within } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { Provider } from 'react-redux'; import { fromJS, Map } from 'immutable'; import { MemoryRouter } from 'react-router-dom';