Skip to content
Snippets Groups Projects
Commit 5581cfce authored by Alexandru Munteanu's avatar Alexandru Munteanu
Browse files

feat(manuscript-details): add editorial comments section

parent 48e17cf7
No related branches found
No related tags found
1 merge request!10Sprint #12
import React from 'react'
import { sortBy } from 'lodash'
import { th } from '@pubsweet/ui'
import styled, { css } from 'styled-components'
import { setDisplayName, withProps, compose } from 'recompose'
import { DateParser } from 'pubsweet-components-faraday/src/components'
const parseRecommendationType = t => {
switch (t) {
case 'reject':
return 'Rejection request'
case 'publish':
return 'Publish request'
default:
return 'Revision request'
}
}
const parseRecommendationComments = (comments = []) =>
sortBy(comments, c => !c.public).map(c => ({
title: c.public ? 'Reason & Details' : 'Internal note',
content: c.content,
}))
const EditorialComment = ({
reason,
comments,
updatedOn,
handlingEditor: { name },
}) => (
<Root>
<Row>
<HeaderContainer>
<ReasonText>{reason}</ReasonText>
<CommentAuthor>{name}</CommentAuthor>
<RoleBadge>he</RoleBadge>
</HeaderContainer>
<DateParser timestamp={updatedOn}>
{t => <DefaultText>{t}</DefaultText>}
</DateParser>
</Row>
{comments.map(({ title, content }) => (
<EditorContainer key={title}>
<ReasonText>{title}</ReasonText>
<DefaultText>{content}</DefaultText>
</EditorContainer>
))}
</Root>
)
export default compose(
setDisplayName('EditorialComment'),
withProps(({ recommendationType, comments = [] }) => ({
reason: parseRecommendationType(recommendationType),
comments: parseRecommendationComments(comments),
})),
)(EditorialComment)
// #region styled-components
const defaultText = css`
color: ${th('colorPrimary')};
font-size: ${th('fontSizeBaseSmall')};
font-family: ${th('fontReading')};
`
const DefaultText = styled.span`
${defaultText};
`
const CommentAuthor = DefaultText.extend`
margin-left: calc(${th('subGridUnit')} * 2);
text-decoration: underline;
`
const RoleBadge = styled.span`
align-items: center;
border: ${th('borderDefault')};
color: ${th('colorPrimary')};
display: flex;
font-family: ${th('fontInterface')};
font-size: 9px;
font-weight: bold;
height: calc(${th('subGridUnit')} * 2);
margin-left: ${th('subGridUnit')};
padding: calc(${th('subGridUnit')} / 3);
text-align: center;
text-transform: uppercase;
`
const HeaderContainer = styled.div`
align-items: center;
display: flex;
`
const ReasonText = DefaultText.extend`
font-family: ${th('fontHeading')};
font-weight: bold;
text-transform: uppercase;
`
const EditorContainer = styled.div`
align-items: flex-start;
display: flex;
flex-direction: column;
`
const Row = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
`
const Root = styled.div`
background-color: ${th('colorBackground')};
border: ${th('borderDefault')};
margin: calc(${th('subGridUnit')} * 2) 0;
padding: calc(${th('subGridUnit')} * 2);
transition: height 0.3s;
`
// #endregion
import React from 'react'
import { get } from 'lodash'
import { th } from '@pubsweet/ui'
import styled from 'styled-components'
import { setDisplayName, withProps, compose } from 'recompose'
import { Expandable } from '../molecules'
import { EditorialComment } from './'
const EditorialComments = ({ recommendations, handlingEditor }) => (
<Root>
<Expandable label="Editorial comments">
{recommendations.map(r => (
<EditorialComment key={r.id} {...r} handlingEditor={handlingEditor} />
))}
</Expandable>
</Root>
)
export default compose(
setDisplayName('EditorialComments'),
withProps(({ project }) => ({
handlingEditor: get(project, 'handlingEditor'),
})),
)(EditorialComments)
// #region styled-components
const Root = styled.div`
background-color: ${th('colorBackground')};
margin-top: calc(${th('subGridUnit')} * 2);
transition: height 0.3s;
`
// #endregion
......@@ -47,7 +47,6 @@ const Text = styled.span`
const Root = styled.div`
background-color: ${th('colorBackground')};
border: ${th('borderDefault')};
margin-top: calc(${th('subGridUnit')} * 2);
transition: height 0.3s;
`
......
......@@ -18,6 +18,7 @@ import {
ReviewsAndReports,
ManuscriptDetails,
ManuscriptVersion,
EditorialComments,
} from './'
const ManuscriptLayout = ({
......@@ -27,6 +28,8 @@ const ManuscriptLayout = ({
currentUserIs,
editorInChief,
updateManuscript,
canSeeEditorialComments,
editorialRecommendations,
project = {},
version = {},
}) => (
......@@ -57,6 +60,13 @@ const ManuscriptLayout = ({
project={project}
version={version}
/>
{canSeeEditorialComments &&
editorialRecommendations.length > 0 && (
<EditorialComments
project={project}
recommendations={editorialRecommendations}
/>
)}
</Container>
<SideBar flex={1}>
<SideBarActions
......
......@@ -11,9 +11,17 @@ import {
selectCurrentUser,
} from 'xpub-selectors'
import { get as apiGet } from 'pubsweet-client/src/helpers/api'
import { compose, lifecycle, withHandlers, withState } from 'recompose'
import {
compose,
lifecycle,
withState,
withProps,
withHandlers,
setDisplayName,
} from 'recompose'
import { getSignedUrl } from 'pubsweet-components-faraday/src/redux/files'
import { reviewerDecision } from 'pubsweet-components-faraday/src/redux/reviewers'
import { selectEditorialRecommendations } from 'pubsweet-components-faraday/src/redux/recommendations'
import {
getHandlingEditors,
selectHandlingEditors,
......@@ -23,6 +31,7 @@ import ManuscriptLayout from './ManuscriptLayout'
import { parseSearchParams, redirectToError } from './utils'
export default compose(
setDisplayName('ManuscriptPage'),
withJournal,
withRouter,
withState('editorInChief', 'setEiC', 'N/A'),
......@@ -39,6 +48,7 @@ export default compose(
handlingEditors: selectHandlingEditors(state),
version: selectFragment(state, match.params.version),
project: selectCollection(state, match.params.project),
editorialRecommendations: selectEditorialRecommendations(state),
}),
{
replace,
......@@ -111,4 +121,9 @@ export default compose(
)
},
}),
withProps(({ project }) => ({
canSeeEditorialComments: ['revisionRequested', 'pendingApproval'].includes(
get(project, 'status'),
),
})),
)(ManuscriptLayout)
......@@ -137,7 +137,6 @@ export default compose(
// #region styled-components
const Root = styled.div`
background-color: ${th('colorBackground')};
border: ${th('borderDefault')};
margin-top: calc(${th('subGridUnit')} * 2);
transition: height 0.3s;
`
......
......@@ -5,10 +5,12 @@ export { default as MakeDecision } from './MakeDecision'
export { default as SideBarRoles } from './SideBarRoles'
export { default as ManuscriptPage } from './ManuscriptPage'
export { default as SideBarActions } from './SideBarActions'
export { default as EditorialComment } from './EditorialComment'
export { default as ReviewReportCard } from './ReviewReportCard'
export { default as ManuscriptHeader } from './ManuscriptHeader'
export { default as ManuscriptLayout } from './ManuscriptLayout'
export { default as ManuscriptDetails } from './ManuscriptDetails'
export { default as ManuscriptVersion } from './ManuscriptVersion'
export { default as ReviewsAndReports } from './ReviewsAndReports'
export { default as EditorialComments } from './EditorialComments'
export { default as ReviewerReportForm } from './ReviewerReportForm'
......@@ -48,25 +48,28 @@ const SectionLabel = styled.span`
const ChildrenContainer = styled.div`
cursor: default;
padding: calc(${th('subGridUnit')} * 3);
padding: calc(${th('subGridUnit')} * 2);
padding-top: 0;
`
const Header = styled.div`
align-items: center;
border-width: 0 0 ${th('borderWidth')} 0;
border-width: 0;
border-bottom-width: ${({ expanded }) => (expanded ? '1px' : 0)};
border-style: ${th('borderStyle')};
border-color: ${th('colorBorder')};
cursor: pointer;
display: flex;
justify-content: flex-start;
margin-bottom: calc(${th('subGridUnit')} * 3);
margin-bottom: ${({ expanded }) => (expanded ? th('subGridUnit') : 0)};
`
const Root = styled.div`
border: ${th('borderDefault')};
cursor: pointer;
display: flex;
flex-direction: column;
margin-top: ${th('subGridUnit')};
transition: all 0.3s;
`
......
import { get } from 'lodash'
import { create, update } from 'pubsweet-client/src/helpers/api'
// #region Constants
const REQUEST = 'recommendations/REQUEST'
const ERROR = 'recommendations/ERROR'
......@@ -8,7 +9,9 @@ const GET_FRAGMENT_SUCCESS = 'GET_FRAGMENT_SUCCESS'
const GET_RECOMMENDATIONS_SUCCESS = 'recommendations/GET_SUCCESS'
const CREATE_RECOMMENDATION_SUCCESS = 'recommendations/CREATE_SUCCESS'
const UPDATE_RECOMMENDATION_SUCCESS = 'recommendations/UPDATE_SUCCESS'
// #endregion
// #region Action Creators
export const recommendationsRequest = () => ({
type: REQUEST,
})
......@@ -32,15 +35,21 @@ export const updateRecommendationSuccess = recommendation => ({
type: UPDATE_RECOMMENDATION_SUCCESS,
payload: { recommendation },
})
// #endregion
// Selectors
// #region Selectors
export const selectFetching = state =>
get(state, 'recommendations.fetching') || false
export const selectError = state => get(state, 'recommendations.error')
export const selectRecommendations = state =>
get(state, 'recommendations.recommendations') || []
export const selectEditorialRecommendations = state =>
selectRecommendations(state).filter(
r => r.recommendationType === 'editorRecommendation',
)
// #endregion
// Actions
// #region Actions
export const createRecommendation = (
collId,
fragId,
......@@ -91,8 +100,9 @@ export const updateRecommendation = (
},
)
}
// #endregion
// State
// #region State
const initialState = {
fetching: false,
error: null,
......@@ -138,3 +148,4 @@ export default (state = initialState, action = {}) => {
return state
}
}
// #endregion
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment