diff --git a/.gitlab-ci.v2.yml b/.gitlab-ci.v2.yml new file mode 100644 index 0000000000000000000000000000000000000000..7bf945c24b2810da8795d439d75df05c678d4e3c --- /dev/null +++ b/.gitlab-ci.v2.yml @@ -0,0 +1,96 @@ +variables: + IMAGE_TAG: latest + IMAGE_ORG: bogdandev + IMAGE_NAME: xpub-faraday + REV_BUCKET: faraday-rollback + CLUSTER_NAME: faraday-qa + CI_PROJECT_NAME: faraday-qa + REPO_URL: https://gitlab.coko.foundation/xpub/xpub-faraday + IMAGE_TAG: $CI_PROJECT_NAME:$CI_COMMIT_SHA + IMAGE_NAME: "$REPOSITORY_URL/$IMAGE_TAG" + +image: docker:stable +services: + - docker:dind + +stages: + - build + - deploy + - test + - rollback + +build: + stage: build + script: + # Setup + - export AWS_REGION="eu-west-1" + - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID + - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY + - export REPO=$REPOSITORY_URL + - apk update + - apk --no-cache add --update curl python python-dev py-pip + - pip install awscli --upgrade --user + - export PATH=~/.local/bin:/usr/bin/:$PATH + # AUTH + - CERT=`aws ecr get-login --no-include-email --region ${AWS_REGION}` + - ${CERT} + # Build + - docker build -t ${CI_PROJECT_NAME}:$CI_COMMIT_SHA . + - docker tag $CI_PROJECT_NAME:$CI_COMMIT_SHA $REPO:latest + - docker push $REPO:latest + environment: + name: staging + +deploy: + stage: deploy + 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 + # Deploy + - ecs deploy --region ${AWS_REGION} ${CLUSTER_NAME} ${CI_PROJECT_NAME} --tag ${CI_COMMIT_SHA} + environment: + name: staging + +test: + stage: test + script: + - export AWS_REGION="us-east-1" + - export AWS_ACCESS_KEY_ID=$aws_access_key_id + - export AWS_SECRET_ACCESS_KEY=$aws_secret_access_key + - apk --no-cache add --update curl python python-dev py-pip jq + - pip install awscli --upgrade --user + - export PATH=~/.local/bin:/usr/bin/:$PATH + # Discover the ALB name + - ALB=`aws elbv2 describe-load-balancers --region ${AWS_REGION} --names ${CI_PROJECT_NAME} | jq .LoadBalancers[0].DNSName` + # Test Keepalive + - /usr/bin/curl --fail http://${ALB//'"'}/keepalive + # IF Keepalive return 200... + # Retrieve & Store this revision as 'last known successful revision' in S3 Bucket + - REV=`aws ecs describe-services --region ${AWS_REGION} --cluster ${CLUSTER_NAME} --service ${CI_PROJECT_NAME} |jq -r '.services[0].deployments[0].taskDefinition'` + - echo successful revision is ${REV} Storing it in S3 Bucket + - echo ${REV} > /${CI_PROJECT_NAME} + # sync rev to S3 here + - aws s3 cp /${CI_PROJECT_NAME} s3://${REV_BUCKET} + environment: + name: staging + +rollback: + stage: rollback + script: + - export AWS_REGION="us-east-1" + - export AWS_ACCESS_KEY_ID=$aws_access_key_id + - export AWS_SECRET_ACCESS_KEY=$aws_secret_access_key + - apk --no-cache add --update curl python python-dev py-pip + - pip install awscli --upgrade --user + - export PATH=~/.local/bin:/usr/bin/:$PATH + - pip install ecs-deploy + - aws s3 cp s3://${REV_BUCKET}/${CI_PROJECT_NAME} ./ + - REV=`cat ./${CI_PROJECT_NAME}` + - echo rev is $REV + - ecs deploy --region ${AWS_REGION} ${CLUSTER_NAME} ${CI_PROJECT_NAME} --task ${REV} + environment: + name: staging + when: on_failure \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c6332261a24060b1135c87873dc2449c1381706a..2794a64779c2d6089d54f626e5514219a70074c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -97,6 +97,7 @@ demo:aws-qa: - export AWS_REGION="eu-west-1" - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY + - eval $(aws ecr get-login --no-include-email --region eu-west-1 | sed 's|https://||') - 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} diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js index 5ccb0a1561c91b4ee5cd4823e4f0c6c1ac9ef340..144d06d425ec7bc68a548b38209772f49459b033 100644 --- a/packages/component-faraday-selectors/src/index.js +++ b/packages/component-faraday-selectors/src/index.js @@ -76,6 +76,14 @@ 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 + if (editorialStatuses.includes(get(collection, 'status'))) return false return true } + +export const getPubsweetError = state => get(state, 'error') + +export const canSeeReviewersReports = (state, collectionId) => { + const isHE = isHEToManuscript(state, collectionId) + const isEiC = currentUserIs(state, 'adminEiC') + return isHE || isEiC +} diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 80537acec66029ed015758b1f13d2ec575a1faf7..ad31c596ca12353cde5542e16f7f0e4c3bfcc543 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react' import { isEmpty } from 'lodash' +import { Redirect } from 'react-router-dom' import { Root, @@ -26,13 +27,16 @@ const ManuscriptLayout = ({ history, currentUser, editorInChief, + pubsweetError, updateManuscript, + canSeeReviewersReports, canSeeEditorialComments, editorialRecommendations, project = {}, version = {}, }) => ( <Root> + {pubsweetError && <Redirect to="not-found" />} {!isEmpty(project) && !isEmpty(version) ? ( <Fragment> <Container flex={3}> @@ -54,12 +58,14 @@ const ManuscriptLayout = ({ version={version} /> <ManuscriptDetails collection={project} fragment={version} /> - <ReviewsAndReports project={project} version={version} /> + {canSeeReviewersReports && ( + <ReviewsAndReports project={project} version={version} /> + )} {canSeeEditorialComments && editorialRecommendations.length > 0 && ( <EditorialComments - project={project} editorInChief={editorInChief} + project={project} recommendations={editorialRecommendations} /> )} diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index e807da9675123c86d5f897df8c54846ec5139677..6825aef0a32ea3d3c45ca5fbe816b21d9f87f96b 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -28,7 +28,11 @@ import { import ManuscriptLayout from './ManuscriptLayout' import { parseSearchParams, redirectToError } from './utils' -import { canSeeEditorialComments } from '../../../component-faraday-selectors' +import { + getPubsweetError, + canSeeReviewersReports, + canSeeEditorialComments, +} from '../../../component-faraday-selectors' export default compose( setDisplayName('ManuscriptPage'), @@ -45,10 +49,15 @@ export default compose( connect( (state, { match }) => ({ currentUser: selectCurrentUser(state), + pubsweetError: getPubsweetError(state), handlingEditors: selectHandlingEditors(state), version: selectFragment(state, match.params.version), project: selectCollection(state, match.params.project), editorialRecommendations: selectEditorialRecommendations(state), + canSeeReviewersReports: canSeeReviewersReports( + state, + match.params.project, + ), canSeeEditorialComments: canSeeEditorialComments( state, match.params.project, diff --git a/packages/components-faraday/src/components/Dashboard/AbstractModal.js b/packages/components-faraday/src/components/Dashboard/AbstractModal.js deleted file mode 100644 index e4a6eb11b9291f6ec3c359784b8d9ab9316f1d31..0000000000000000000000000000000000000000 --- a/packages/components-faraday/src/components/Dashboard/AbstractModal.js +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react' -import { get } from 'lodash' -import { Icon, th } from '@pubsweet/ui' -import styled, { css } from 'styled-components' - -const AbstractModal = ({ metadata, hideModal }) => ( - <Root> - <CloseIcon onClick={hideModal}> - <Icon primary>x</Icon> - </CloseIcon> - <Title dangerouslySetInnerHTML={{ __html: get(metadata, 'title') }} /> - <Subtitle>Abstract</Subtitle> - <Content dangerouslySetInnerHTML={{ __html: get(metadata, 'abstract') }} /> - </Root> -) - -export default AbstractModal - -// #region styled-components -const defaultText = css` - color: ${th('colorText')}; - font-family: ${th('fontReading')}; - font-size: ${th('fontSizeBaseSmall')}; -` - -const Root = styled.div` - background-color: ${th('backgroundColor')}; - border: ${th('borderDefault')}; - max-height: 500px; - padding: ${th('gridUnit')}; - padding-top: calc(${th('gridUnit')} * 2); - position: relative; - overflow-y: scroll; - width: 600px; -` - -const Title = styled.div` - ${defaultText}; - font-size: ${th('fontSizeBase')}; - text-align: left; -` - -const Subtitle = styled.div` - ${defaultText}; - font-weight: bold; - line-height: 1.57; - margin-bottom: ${th('subGridUnit')}; - text-align: left; -` - -const Content = styled.div` - ${defaultText}; - line-height: 1.57; - margin-top: calc(${th('subGridUnit')} * 2); - text-align: left; -` - -const CloseIcon = styled.div` - cursor: pointer; - position: absolute; - top: ${th('subGridUnit')}; - right: ${th('subGridUnit')}; -` -// #endregion diff --git a/packages/components-faraday/src/components/Dashboard/Dashboard.js b/packages/components-faraday/src/components/Dashboard/Dashboard.js index c0d8486c61f535ccc961337c6d2f7ad7e92b5a2f..c740018baa68358e10070e8457e3d53019086945 100644 --- a/packages/components-faraday/src/components/Dashboard/Dashboard.js +++ b/packages/components-faraday/src/components/Dashboard/Dashboard.js @@ -15,7 +15,6 @@ const Dashboard = ({ deleteProject, getFilterOptions, changeFilterValue, - showAbstractModal, createDraftSubmission, ...rest }) => ( @@ -36,22 +35,12 @@ const Dashboard = ({ changeFilterValue={changeFilterValue} getFilterOptions={getFilterOptions} /> - <DashboardItems - deleteProject={deleteProject} - list={getItems()} - showAbstractModal={showAbstractModal} - /> + <DashboardItems deleteProject={deleteProject} list={getItems()} /> </Root> ) export default compose( withHandlers({ - showAbstractModal: ({ showModal }) => metadata => () => { - showModal({ - metadata, - dismissable: true, - }) - }, getItems: ({ filters, dashboard, diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js index 8022eea61cba058d8924d326b3962bb040df35bd..a3d0cd20d2644651a6b315085ba12117ee8c24c0 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js @@ -34,7 +34,6 @@ const DashboardCard = ({ currentUser, deleteProject, canMakeDecision, - showAbstractModal, canInviteReviewers, canMakeRecommendation, ...rest @@ -45,6 +44,7 @@ const DashboardCard = ({ const customId = project.customId || project.id.split('-')[0] const hasFiles = files ? Object.values(files).some(f => f.length > 0) : false const journalIssueType = parseJournalIssue(journal, metadata) + const submittedDate = get(version, 'submitted') const manuscriptMeta = `${type} - ${ journalIssueType ? journalIssueType.label : 'N/A' }` @@ -102,16 +102,15 @@ const DashboardCard = ({ <Bottom> <LeftDetails flex={3}> <Status>{mapStatusToLabel(project)}</Status> - <DateParser - durationThreshold={0} - timestamp={get(version, 'submitted')} - > - {(timestamp, daysAgo) => ( - <DateField> - {timestamp} ({daysAgo} ago) - </DateField> - )} - </DateParser> + {submittedDate && ( + <DateParser durationThreshold={0} timestamp={submittedDate}> + {(timestamp, daysAgo) => ( + <DateField> + {timestamp} ({daysAgo} ago) + </DateField> + )} + </DateParser> + )} </LeftDetails> <RightDetails flex={4}> <ManuscriptType title={manuscriptMeta}> diff --git a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js index 88f5737f4503db0ee0d956e9161de98188cfd8c8..0d0cfbd37e1011ff5b9ea562abd77b16e67d8e43 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardFilters.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardFilters.js @@ -4,7 +4,7 @@ import { Menu, th } from '@pubsweet/ui' import { compose, withHandlers } from 'recompose' const DashboardFilters = ({ - view, + // view, status, listView, createdAt, diff --git a/packages/components-faraday/src/components/Dashboard/DashboardItems.js b/packages/components-faraday/src/components/Dashboard/DashboardItems.js index 8e898b79aa5c2d52ccd25704c84703870fc93ae8..172ad34619239249c2ab126a0ad550f27f149dc9 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardItems.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardItems.js @@ -6,12 +6,7 @@ import withVersion from './withVersion' const DashboardItem = withVersion(Item) -const DashboardItems = ({ - list, - deleteProject, - listView = true, - showAbstractModal, -}) => ( +const DashboardItems = ({ list, deleteProject, listView = true }) => ( <div> {!list.length && ( <Empty>Nothing to do at the moment. Please upload a manuscript.</Empty> @@ -25,7 +20,6 @@ const DashboardItems = ({ key={p.id} listView={listView} project={p} - showAbstractModal={showAbstractModal} /> ))} </Section> diff --git a/packages/components-faraday/src/components/Dashboard/DeleteManuscript.js b/packages/components-faraday/src/components/Dashboard/DeleteManuscript.js index bb401928e2d87a71b9fa62c8532077634b8a8dab..7f53c759ec14ec14e857ba01ba6aae12b683b03d 100644 --- a/packages/components-faraday/src/components/Dashboard/DeleteManuscript.js +++ b/packages/components-faraday/src/components/Dashboard/DeleteManuscript.js @@ -1,5 +1,4 @@ import React from 'react' -import { get } from 'lodash' import { th } from '@pubsweet/ui' import styled from 'styled-components' import { compose, withHandlers, setDisplayName } from 'recompose' @@ -8,6 +7,8 @@ import { ConfirmationModal, } from 'pubsweet-component-modal/src/components' +import { handleError } from '../utils' + const DeleteManuscript = ({ confirmDelete }) => ( <Details onClick={confirmDelete}>Delete</Details> ) @@ -20,20 +21,15 @@ export default compose( withHandlers({ confirmDelete: ({ showModal, + hideModal, deleteProject, setModalError, - hideModal, }) => () => { showModal({ confirmText: 'Delete', title: 'Are you sure you want to delete this submission?', onConfirm: () => { - deleteProject().then(hideModal, e => { - setModalError( - get(JSON.parse(e.response), 'error') || - 'Oops! Something went wrong!', - ) - }) + deleteProject().then(hideModal, handleError(setModalError)) }, }) }, diff --git a/packages/components-faraday/src/components/Dashboard/ReviewerDecision.js b/packages/components-faraday/src/components/Dashboard/ReviewerDecision.js index 2636b09b5574ef28ea98431c46522a421510ce5c..6dece3361cd054c3615dd6df96e0be77ae086e92 100644 --- a/packages/components-faraday/src/components/Dashboard/ReviewerDecision.js +++ b/packages/components-faraday/src/components/Dashboard/ReviewerDecision.js @@ -8,6 +8,8 @@ import { withModal, ConfirmationModal, } from 'pubsweet-component-modal/src/components' + +import { handleError } from '../utils' import { selectFetchingDecision, reviewerDecision } from '../../redux/reviewers' const ReviewerDecision = ({ showAcceptModal, showDeclineModal, ...rest }) => ( @@ -44,6 +46,7 @@ export default compose( project, showModal, invitation, + setModalError, decisionSuccess, reviewerDecision, }) => () => { @@ -53,6 +56,7 @@ export default compose( onConfirm: () => { reviewerDecision(invitation.id, project.id, true).then( decisionSuccess, + handleError(setModalError), ) }, }) @@ -61,6 +65,7 @@ export default compose( project, showModal, invitation, + setModalError, decisionSuccess, reviewerDecision, }) => () => { @@ -70,6 +75,7 @@ export default compose( onConfirm: () => { reviewerDecision(invitation.id, project.id, false).then( decisionSuccess, + handleError(setModalError), ) }, }) @@ -85,7 +91,7 @@ const defaultText = css` const DecisionButton = styled(Button)` ${defaultText}; - align-items: center; + align-items: center; background-color: ${({ primary }) => primary ? th('colorPrimary') : th('backgroundColorReverse')}; color: ${({ primary }) => diff --git a/packages/components-faraday/src/components/Dashboard/index.js b/packages/components-faraday/src/components/Dashboard/index.js index 365a49a2cc8ad66ac09003bcc4d199fa3961b736..a0b4c9cd8cf85f6e7cf5a8ae9caa592fc3e78e92 100644 --- a/packages/components-faraday/src/components/Dashboard/index.js +++ b/packages/components-faraday/src/components/Dashboard/index.js @@ -1,7 +1,6 @@ import DashboardPage from './DashboardPage' export { default as Dashboard } from './Dashboard' -export { default as AbstractModal } from './AbstractModal' export { default as AuthorTooltip } from './AuthorTooltip' export { default as DashboardCard } from './DashboardCard' export { default as DashboardItems } from './DashboardItems' diff --git a/packages/components-faraday/src/components/UIComponents/NotFound.js b/packages/components-faraday/src/components/UIComponents/NotFound.js index 6a4ed011b9032275b27f45bb30e0bc3825e8296f..d2f0e78ec0a68bc4197633cc03325d6eef539572 100644 --- a/packages/components-faraday/src/components/UIComponents/NotFound.js +++ b/packages/components-faraday/src/components/UIComponents/NotFound.js @@ -12,8 +12,8 @@ const NotFound = ({ history }) => ( The page you are looking for might have been removed, had its name changed, or is temporarily unavailable. </H3> - <Button onClick={history.goBack} primary> - Back + <Button onClick={() => history.push('/')} primary> + Go to dashboard </Button> </Root> ) diff --git a/packages/components-faraday/src/components/utils.js b/packages/components-faraday/src/components/utils.js index e4734a369ac88f22b61fcc490d87b87e547ddc83..1780bd7a318d551ee2fb4dfa5a03c2dbb03be8e1 100644 --- a/packages/components-faraday/src/components/utils.js +++ b/packages/components-faraday/src/components/utils.js @@ -1,4 +1,3 @@ -import moment from 'moment' import { get, find, capitalize } from 'lodash' export const parseTitle = version => { @@ -19,22 +18,9 @@ export const parseType = version => { 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 parseVersion = version => ({ author: parseAuthor(version), title: parseTitle(version), - submitted: parseSubmissionDate(version), type: parseType(version), abstract: get(version, 'metadata.abstract'), version: get(version, 'version'),