diff --git a/packages/component-manuscript/src/atoms/index.js b/packages/component-manuscript/src/atoms/index.js index af47591164adbddb4a11b8bb511c14a6905e67cd..30932299b45491a8f2580266bdae021f3d25052b 100644 --- a/packages/component-manuscript/src/atoms/index.js +++ b/packages/component-manuscript/src/atoms/index.js @@ -16,8 +16,10 @@ const Title = styled.div` ${defaultText}; font-size: ${th('fontSizeBase')}; color: ${th('colorPrimary')}; - margin-bottom: ${th('gridUnit')}; text-align: left; + p { + margin: 0; + } ` const Container = styled.div` @@ -35,6 +37,7 @@ const Header = styled.div` align-items: center; display: flex; flex-direction: row; + margin-bottom: ${th('subGridUnit')}; ` const BreadCrumbs = styled.div` @@ -62,7 +65,7 @@ const ManuscriptId = styled.div` ${defaultText}; color: ${th('colorPrimary')}; font-size: ${th('fontSizeBase')}; - margin-right: 8px; + margin-right: ${th('subGridUnit')}; text-align: left; text-transform: uppercase; white-space: nowrap; @@ -102,6 +105,29 @@ const DateField = styled.span` margin: 0 ${th('subGridUnit')}; text-align: left; ` +const Row = styled.div` + display: flex; + flex-direction: row; + align-items: center; + width: 100%; + box-sizing: border-box; +` + +const ManuscriptType = styled.div` + ${defaultText}; + padding: ${th('subGridUnit')}; + margin-left: calc(${th('subGridUnit')}*2); + text-align: right; + text-transform: capitalize; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +` + +const ManuscriptHeader = styled.div` + border-bottom: ${th('borderDefault')}; + padding-bottom: calc(${th('subGridUnit')}*2); +` export { Root, @@ -109,10 +135,13 @@ export { Header, Title, ManuscriptId, + ManuscriptType, Container, SideBar, LeftDetails, RightDetails, StatusLabel, DateField, + Row, + ManuscriptHeader, } diff --git a/packages/component-manuscript/src/components/ManuscriptDetails.js b/packages/component-manuscript/src/components/ManuscriptDetails.js deleted file mode 100644 index fbef181efe918f594fa3bf896e622113241ca8eb..0000000000000000000000000000000000000000 --- a/packages/component-manuscript/src/components/ManuscriptDetails.js +++ /dev/null @@ -1,15 +0,0 @@ -import React, { Fragment } from 'react' -// import { AuthorsWithTooltip } from '@pubsweet/ui' - -import { Title } from '../atoms' - -import AuthorsWithTooltip from '../molecules/AuthorsWithTooltip' - -const ManuscriptDetails = ({ version, project }) => ( - <Fragment> - <Title dangerouslySetInnerHTML={{ __html: version.metadata.title }} /> - <AuthorsWithTooltip authors={project.authors} /> - </Fragment> -) - -export default ManuscriptDetails diff --git a/packages/component-manuscript/src/components/ManuscriptHeader.js b/packages/component-manuscript/src/components/ManuscriptHeader.js new file mode 100644 index 0000000000000000000000000000000000000000..03f49d508ad381bf1e057127748ada78814c2ded --- /dev/null +++ b/packages/component-manuscript/src/components/ManuscriptHeader.js @@ -0,0 +1,45 @@ +import React from 'react' +import { get } from 'lodash' +// import { AuthorsWithTooltip } from '@pubsweet/ui' + +import { + Title, + LeftDetails, + RightDetails, + Row, + StatusLabel, + DateField, + ManuscriptType, + ManuscriptHeader, +} from '../atoms' + +import { parseVersion, parseJournalIssue, mapStatusToLabel } from './utils' +import AuthorsWithTooltip from '../molecules/AuthorsWithTooltip' + +const ManuscriptDetails = ({ version, project, journal }) => { + const { submitted, title, type } = parseVersion(version) + const metadata = get(version, 'metadata') + const journalIssueType = parseJournalIssue(journal, metadata) + const manuscriptMeta = `${type} - ${ + journalIssueType ? journalIssueType.label : 'N/A' + }` + return ( + <ManuscriptHeader> + <Title dangerouslySetInnerHTML={{ __html: title }} /> + <Row> + <LeftDetails flex={3}> + <StatusLabel>{mapStatusToLabel(project)}</StatusLabel> + <DateField>{submitted || ''}</DateField> + </LeftDetails> + <RightDetails flex={4}> + <ManuscriptType title={manuscriptMeta}> + {manuscriptMeta} + </ManuscriptType> + </RightDetails> + </Row> + <AuthorsWithTooltip authors={project.authors} /> + </ManuscriptHeader> + ) +} + +export default ManuscriptDetails diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 7c852d0b8b10e13ee83053da03f3897a090347ad..ae4ea0de6aa228117a0f4de448f413e29fcc2539 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -1,6 +1,6 @@ import React from 'react' -import ManuscriptDetails from './ManuscriptDetails' +import ManuscriptHeader from './ManuscriptHeader' import { Root, BreadCrumbs, @@ -15,6 +15,7 @@ const ManuscriptLayout = ({ updateManuscript, project, version, + journal, }) => ( <Root> <Container flex={3}> @@ -25,7 +26,7 @@ const ManuscriptLayout = ({ </BreadCrumbs> <ManuscriptId>{`- ID ${project.customId}`}</ManuscriptId> </Header> - <ManuscriptDetails project={project} version={version} /> + <ManuscriptHeader journal={journal} project={project} version={version} /> </Container> <SideBar flex={1}>Sidebar</SideBar> </Root> diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index 091de333fb7acdc054de6f5cb42156ec29ce8030..0179406874f89e00b929d56de0f74446ddc48cbe 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux' import { actions } from 'pubsweet-client' import { ConnectPage } from 'xpub-connect' +import { withJournal } from 'xpub-journal' import { selectCurrentUser, selectCollection, @@ -14,6 +15,7 @@ import { parseSearchParams, redirectToError } from './utils' import { reviewerDecision } from '../../../components-faraday/src/redux/reviewers' export default compose( + withJournal, ConnectPage(({ match }) => [ actions.getCollection({ id: match.params.project }), actions.getFragment( diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js index 9aed3777b03c8afb27cc7556190c9f7d1130ae83..aa176d4c0292a377118aa05ee4a66b9492a877b6 100644 --- a/packages/component-manuscript/src/components/utils.js +++ b/packages/component-manuscript/src/components/utils.js @@ -1,12 +1,65 @@ -/* eslint-disable */ -import { get } from 'lodash' +import moment from 'moment' +import { get, find, capitalize } from 'lodash' + +export const parseTitle = version => { + const title = get(version, 'metadata.title') + if (title) { + return title.replace(/<p[^>]*>/g, '').replace(/<\/p>/g, '') + } + return 'Untitled' +} + +export const parseAuthor = version => { + const author = find(get(version, 'authors'), a => a.isSubmitting) + return author ? `${author.firstName} ${author.lastName}` : 'N/A' +} + +export const parseType = version => { + const type = get(version, 'metadata.type') + return type ? type.replace('-', ' ') : 'N/A' +} + +export const parseSubmissionDate = version => { + const submitted = get(version, 'submitted') + const submittedDate = moment(submitted) + const today = moment() + const daysAgo = moment.duration(today - moment(submitted)).days() + return submitted + ? `${submittedDate.format('DD.MM.YYYY')} ${ + daysAgo > 0 ? `(${daysAgo} days)` : '' + }` + : 'N/A' +} + +export const mapStatusToLabel = ({ visibleStatus, status }) => { + if (visibleStatus) { + return visibleStatus + } else if (status) { + return capitalize(status) + } + return 'Draft' +} + +export const parseVersion = version => ({ + author: parseAuthor(version), + title: parseTitle(version), + submitted: parseSubmissionDate(version), + type: parseType(version), + abstract: get(version, 'metadata.abstract'), + version: get(version, 'version'), +}) + +export const parseJournalIssue = (journal, metadata) => + journal.issueTypes.find(t => t.value === get(metadata, 'issue')) export const parseSearchParams = url => { const params = new URLSearchParams(url) const parsedObject = {} + /* eslint-disable */ for ([key, value] of params) { parsedObject[key] = value } + /* eslint-enable */ return parsedObject }