diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 06f341ba55a558d9df28a11570dfd56cfb3b1938..c6332261a24060b1135c87873dc2449c1381706a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -83,6 +83,24 @@ demo:qa: - now --public --docker --token $NOW_TOKEN -e AWS_S3_ACCESS_KEY=$AWS_S3_ACCESS_KEY -e AWS_S3_SECRET_KEY=$AWS_S3_SECRET_KEY -e AWS_S3_REGION=$AWS_S3_REGION -e AWS_S3_BUCKET=$AWS_S3_BUCKET -e AWS_SES_SECRET_KEY=$AWS_SES_SECRET_KEY -e AWS_SES_ACCESS_KEY=$AWS_SES_ACCESS_KEY -e AWS_SES_REGION=$AWS_SES_REGION -e EMAIL_SENDER=$EMAIL_SENDER -e secret=$SECRET -e DATABASE=$DATABASE -e DB_USER=$DB_USER -e DB_PASS=$DB_PASS -e DB_HOST=$DB_HOST - now alias $NOW_URL xpub-faraday-qa --token $NOW_TOKEN +demo:aws-qa: + image: $REPOSITORY_URL:latest + stage: demo + when: manual + variables: + PACKAGE_NAME: xpub-faraday + CLUSTER_NAME: faraday-cluster + environment: + name: qa/$PACKAGE_NAME + url: http://52.211.238.137/ + script: + - export AWS_REGION="eu-west-1" + - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID + - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY + - apk --no-cache add --update python python-dev py-pip + - pip install ecs-deploy + - ecs deploy --region ${AWS_REGION} ${CLUSTER_NAME} ${IMAGE_REPO}:${CI_COMMIT_SHA} --tag ${CI_COMMIT_SHA} + demo:staging: image: $IMAGE_ORG/$IMAGE_NAME:$CI_COMMIT_SHA stage: demo diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js index 277860ce91040a4793ecca2054db30e56c09bdfc..5ccb0a1561c91b4ee5cd4823e4f0c6c1ac9ef340 100644 --- a/packages/component-faraday-selectors/src/index.js +++ b/packages/component-faraday-selectors/src/index.js @@ -30,7 +30,7 @@ export const currentUserIs = ({ currentUser: { user } }, role) => { export const canInviteReviewers = ({ currentUser: { user } }, project) => { const status = get(project, 'status') - if (!status || status === 'rejected') return false + if (!status || status === 'rejected' || status === 'published') return false const handlingEditor = get(project, 'handlingEditor') const isAdmin = get(user, 'admin') @@ -59,8 +59,23 @@ export const getHERecommendation = (state, collectionId, fragmentId) => { export const canMakeDecision = (state, collection) => { const status = get(collection, 'status') - if (!status || status === 'rejected') return false + if (!status || status === 'rejected' || status === 'published') return false const isEIC = currentUserIs(state, 'adminEiC') return isEIC && status } + +const editorialStatuses = [ + 'rejected', + 'published', + 'pendingApproval', + 'revisionRequested', +] + +export const canSeeEditorialComments = (state, collectionId) => { + const collection = state.collections.find(c => c.id === collectionId) + const isStaff = currentUserIs(state, 'staff') + if (!isStaff) return false + if (!editorialStatuses.includes(collection.status)) return false + return true +} diff --git a/packages/component-manuscript/src/components/EditorialComment.js b/packages/component-manuscript/src/components/EditorialComment.js index b595b7907f774441dc24d5be38037638697d0d0e..c5e8838193406e423d40a283ba0ceddfb7b0009b 100644 --- a/packages/component-manuscript/src/components/EditorialComment.js +++ b/packages/component-manuscript/src/components/EditorialComment.js @@ -26,14 +26,14 @@ const EditorialComment = ({ reason, comments, updatedOn, - handlingEditor: { name }, + author: { name, role }, }) => ( <Root> <Row> <HeaderContainer> <ReasonText>{reason}</ReasonText> <CommentAuthor>{name}</CommentAuthor> - <RoleBadge>he</RoleBadge> + <RoleBadge>{role}</RoleBadge> </HeaderContainer> <DateParser timestamp={updatedOn}> {t => <DefaultText>{t}</DefaultText>} @@ -50,10 +50,22 @@ const EditorialComment = ({ export default compose( setDisplayName('EditorialComment'), - withProps(({ recommendation, comments = [] }) => ({ - reason: parseRecommendationType(recommendation), - comments: parseRecommendationComments(comments), - })), + withProps( + ({ + userId, + editorInChief, + recommendation, + handlingEditor: { id: heId, name: heName }, + comments = [], + }) => ({ + reason: parseRecommendationType(recommendation), + comments: parseRecommendationComments(comments), + author: { + name: userId === heId ? heName : editorInChief, + role: userId === heId ? 'HE' : 'EiC', + }, + }), + ), )(EditorialComment) // #region styled-components @@ -84,7 +96,6 @@ const RoleBadge = styled.span` margin-left: ${th('subGridUnit')}; padding: calc(${th('subGridUnit')} / 3); text-align: center; - text-transform: uppercase; ` const HeaderContainer = styled.div` diff --git a/packages/component-manuscript/src/components/EditorialComments.js b/packages/component-manuscript/src/components/EditorialComments.js index 591c9f31a4da8bb1989d768ada8c660844e6d027..d362434c9bbf4491535f75fa64d01626154a5170 100644 --- a/packages/component-manuscript/src/components/EditorialComments.js +++ b/packages/component-manuscript/src/components/EditorialComments.js @@ -7,11 +7,20 @@ import { setDisplayName, withProps, compose } from 'recompose' import { Expandable } from '../molecules' import { EditorialComment } from './' -const EditorialComments = ({ recommendations, handlingEditor }) => ( +const EditorialComments = ({ + recommendations, + handlingEditor, + editorInChief, +}) => ( <Root> <Expandable label="Editorial comments" startExpanded> {recommendations.map(r => ( - <EditorialComment key={r.id} {...r} handlingEditor={handlingEditor} /> + <EditorialComment + key={r.id} + {...r} + editorInChief={editorInChief} + handlingEditor={handlingEditor} + /> ))} </Expandable> </Root> diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 556a1f4a50451995093ff33c3b6958f1235978d6..80537acec66029ed015758b1f13d2ec575a1faf7 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -59,6 +59,7 @@ const ManuscriptLayout = ({ editorialRecommendations.length > 0 && ( <EditorialComments project={project} + editorInChief={editorInChief} recommendations={editorialRecommendations} /> )} diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index 22a30f30ba801668a28205b819c60c136575fae4..e807da9675123c86d5f897df8c54846ec5139677 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -28,6 +28,7 @@ import { import ManuscriptLayout from './ManuscriptLayout' import { parseSearchParams, redirectToError } from './utils' +import { canSeeEditorialComments } from '../../../component-faraday-selectors' export default compose( setDisplayName('ManuscriptPage'), @@ -48,6 +49,10 @@ export default compose( version: selectFragment(state, match.params.version), project: selectCollection(state, match.params.project), editorialRecommendations: selectEditorialRecommendations(state), + canSeeEditorialComments: canSeeEditorialComments( + state, + match.params.project, + ), }), { replace, diff --git a/packages/component-manuscript/src/components/SideBarActions.js b/packages/component-manuscript/src/components/SideBarActions.js index 5d4befd132fce1bdd798db8e03082773836bca66..01f60511fa7ccfb30a467976c768c876c80e4fe2 100644 --- a/packages/component-manuscript/src/components/SideBarActions.js +++ b/packages/component-manuscript/src/components/SideBarActions.js @@ -58,7 +58,7 @@ export default compose( const Root = styled.div` border-bottom: ${th('borderDefault')}; display: flex; - justify-content: space-between; + justify-content: flex-end; padding: ${th('subGridUnit')}; ` diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js index 5b7fa5a43bd670979268afedf48de276dce39c3a..8022eea61cba058d8924d326b3962bb040df35bd 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js @@ -102,10 +102,13 @@ const DashboardCard = ({ <Bottom> <LeftDetails flex={3}> <Status>{mapStatusToLabel(project)}</Status> - <DateParser timestamp={get(version, 'submitted')}> + <DateParser + durationThreshold={0} + timestamp={get(version, 'submitted')} + > {(timestamp, daysAgo) => ( <DateField> - {timestamp} ({daysAgo}) + {timestamp} ({daysAgo} ago) </DateField> )} </DateParser> diff --git a/packages/components-faraday/src/components/MakeDecision/utils.js b/packages/components-faraday/src/components/MakeDecision/utils.js index 1ca6f60c95255df906ddafea621fd5895bce0f17..398b188fac3713c5a628b5ae667c2ea048ffac3e 100644 --- a/packages/components-faraday/src/components/MakeDecision/utils.js +++ b/packages/components-faraday/src/components/MakeDecision/utils.js @@ -24,7 +24,7 @@ export const parseFormValues = ({ decision, messageToHE }) => { recommendation: decision, recommendationType: 'editorRecommendation', } - return messageToHE + return decision === 'return-to-handling-editor' ? { ...recommendation, comments: [ diff --git a/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js b/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js index 8dfad00eeb82e02604cbb60fb805c42b87fd5e54..3b69d0fb2a5563e425abeaf9cdd985fc910d6105 100644 --- a/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js +++ b/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js @@ -52,7 +52,7 @@ const TR = ({ </DateParser> <td> <StatusText> - {`${r.status === 'accepted' ? 'Agreed: ' : r.status}`} + {`${r.status === 'accepted' ? 'Agreed: ' : `${r.status}: `}`} </StatusText> <DateParser timestamp={r.respondedOn}> {timestamp => <DateText>{timestamp}</DateText>} diff --git a/packages/components-faraday/src/components/UIComponents/DateParser.js b/packages/components-faraday/src/components/UIComponents/DateParser.js index 5ff1623f3983cb4b2d603f21c6eac96d15139be2..b883807368f6e6e767ea39e1ca57853c987722a4 100644 --- a/packages/components-faraday/src/components/UIComponents/DateParser.js +++ b/packages/components-faraday/src/components/UIComponents/DateParser.js @@ -1,5 +1,6 @@ import moment from 'moment' import { compose, withProps, withHandlers } from 'recompose' +import { string, instanceOf, number, oneOfType } from 'prop-types' const getDuration = timestamp => { const today = moment() @@ -7,17 +8,20 @@ const getDuration = timestamp => { return moment.duration(today.diff(stamp)) } -const DateParser = ({ children, timestamp, daysAgo }) => - children(timestamp, daysAgo) +const D = ({ children, timestamp, daysAgo }) => children(timestamp, daysAgo) -export default compose( +const DateParser = compose( withHandlers({ - renderTimestamp: ({ timestamp, dateFormat = 'DD.MM.YYYY' }) => () => { + renderTimestamp: ({ + timestamp, + durationThreshold = 1, + dateFormat = 'DD.MM.YYYY', + }) => () => { if (!timestamp) return '' const duration = getDuration(timestamp) - if (duration.asDays() < 1) { - return `${duration.humanize()}` + if (duration.asDays() < durationThreshold) { + return `${duration.humanize()} ago` } return moment(timestamp).format(dateFormat) }, @@ -31,4 +35,12 @@ export default compose( daysAgo: renderDaysAgo(), timestamp: renderTimestamp(), })), -)(DateParser) +)(D) + +DateParser.propTypes = { + dateFormat: string, + durationThreshold: number, + timestamp: oneOfType([string, number, instanceOf(Date)]), +} + +export default DateParser diff --git a/packages/components-faraday/src/redux/recommendations.js b/packages/components-faraday/src/redux/recommendations.js index 3decec77f2040fad93a44139f26a10368c0ebacc..a85e13f8c34818166263789e08c10df7d76ff3be 100644 --- a/packages/components-faraday/src/redux/recommendations.js +++ b/packages/components-faraday/src/redux/recommendations.js @@ -45,7 +45,7 @@ export const selectRecommendations = state => get(state, 'recommendations.recommendations') || [] export const selectEditorialRecommendations = state => selectRecommendations(state).filter( - r => r.recommendationType === 'editorRecommendation', + r => r.recommendationType === 'editorRecommendation' && r.comments, ) // #endregion diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js index 88f4b83d333383179fffa23d9403a76e319c2502..948dd93e25476745ef93e4db143ff99f79ff8cec 100644 --- a/packages/xpub-faraday/config/authsome-mode.js +++ b/packages/xpub-faraday/config/authsome-mode.js @@ -244,7 +244,7 @@ const authsomeMode = async (userId, operation, object, context) => { const user = await context.models.User.find(userId) // Admins and editor in chiefs can do anything - if (user && (user.admin === true || user.editorInChief === true)) return true + if (user && (user.admin || user.editorInChief)) return true if (user) { return authenticatedUser(user, operation, object, context)