diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js
index 8a6ef140784a77427e9da1f5095a39a3148efaea..f265fd9dc0b366803c2eac1c74d5772e6ba79269 100644
--- a/packages/component-faraday-selectors/src/index.js
+++ b/packages/component-faraday-selectors/src/index.js
@@ -1,5 +1,5 @@
-import { get, has, last, chain, some } from 'lodash'
 import { selectCurrentUser } from 'xpub-selectors'
+import { get, has, last, chain, some } from 'lodash'
 
 export const isHEToManuscript = (state, collectionId = '') => {
   const { id = '', isAccepted = false } = chain(state)
@@ -199,9 +199,7 @@ export const getHERecommendation = (state, collectionId, fragmentId) => {
 }
 
 const canMakeDecisionStatuses = ['submitted', 'pendingApproval']
-export const canMakeDecision = (state, collection = {}, fragment = {}) => {
-  if (get(fragment, 'id', '') !== last(get(collection, 'fragments', [])))
-    return false
+export const canMakeDecision = (state, collection = {}) => {
   const status = get(collection, 'status', 'draft')
 
   const isEIC = currentUserIs(state, 'adminEiC')
@@ -372,6 +370,9 @@ export const canMakeHERecommendation = (state, { collection, statuses }) => {
   return statusImportance > 1 && statusImportance < 9 && validHE
 }
 
+export const getFragmentAuthorResponse = (state, fragmentId) =>
+  get(state, `fragments.${fragmentId}.responseToReviewers`, {})
+
 // #region Editorial and reviewer recommendations
 export const getFragmentRecommendations = (state, fragmentId) =>
   get(state, `fragments.${fragmentId}.recommendations`, [])
@@ -409,18 +410,6 @@ export const getOwnSubmittedRecommendation = (state, fragmentId) =>
     )
     .value()
 
-const canMakeRecommendationStatuses = [
-  'heAssigned',
-  'underReview',
-  'reviewCompleted',
-]
-export const canMakeRecommendation = (state, collection, fragment = {}) => {
-  if (fragment.id !== last(get(collection, 'fragments', []))) return false
-  const isHE = isHEToManuscript(state, get(collection, 'id', ''))
-  const status = get(collection, 'status', 'draft')
-  return isHE && canMakeRecommendationStatuses.includes(status)
-}
-
 export const canSubmitRevision = (state, fragment = {}) => {
   const userId = get(state, 'currentUser.user.id')
   const fragmentAuthors = chain(fragment)
@@ -450,3 +439,14 @@ export const getVersionOptions = (state, collection = {}) => {
     .reverse()
     .value()
 }
+
+export const canReview = (state, collection = {}, fragment = {}) => {
+  const fragmentId = get(fragment, 'id', false)
+
+  if (!fragmentId) return false
+
+  const isReviewer = currentUserIsReviewer(state, fragmentId)
+  if (!isReviewer) return false
+
+  return get(collection, 'status', 'draft') === 'underReview'
+}
diff --git a/packages/component-faraday-ui/src/ActionLink.js b/packages/component-faraday-ui/src/ActionLink.js
index 9f27cec30d1ba8e1584fed2f753653c952e23f77..05ad25cd28ff0ec15c333469b13f6ec6c16e9402 100644
--- a/packages/component-faraday-ui/src/ActionLink.js
+++ b/packages/component-faraday-ui/src/ActionLink.js
@@ -78,7 +78,7 @@ const Root = styled.div`
   ${marginHelper};
   ${paddingHelper};
 
-  height: max-content;
+  height: ${props => (props.height ? `${props.height}px` : 'max-content')};
   width: max-content;
 
   & span {
diff --git a/packages/component-faraday-ui/src/AuthorReply.js b/packages/component-faraday-ui/src/AuthorReply.js
new file mode 100644
index 0000000000000000000000000000000000000000..22649c9636aba91856d4fef278b074951b73b6b7
--- /dev/null
+++ b/packages/component-faraday-ui/src/AuthorReply.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import { get } from 'lodash'
+import { withProps } from 'recompose'
+import styled from 'styled-components'
+import { th } from '@pubsweet/ui-toolkit'
+import { DateParser } from '@pubsweet/ui'
+
+import { Label, Item, Row, Text } from './'
+
+const submittingAuthor = authors => {
+  const thisAuthor = authors.filter(e => e.isSubmitting)
+  return thisAuthor[0]
+}
+
+const AuthorReply = ({ reply, authorName, submittedOn }) => (
+  <Root>
+    <Row justify="space-between" mb={2}>
+      <Item justify="flex-end">
+        <Row mb={1}>
+          <Item vertical>
+            <Label mb={1 / 2}>Author Reply</Label>
+            <Text>{reply}</Text>
+          </Item>
+        </Row>
+        <Text ml={1} mr={1} whiteSpace="nowrap">
+          {authorName}
+        </Text>
+        <DateParser timestamp={submittedOn}>
+          {date => <Text>{date}</Text>}
+        </DateParser>
+      </Item>
+    </Row>
+  </Root>
+)
+
+export default withProps(({ fragment: { authors, submitted } }) => ({
+  submittedOn: submitted,
+  authorName: `${get(submittingAuthor(authors), 'firstName', '')} ${get(
+    submittingAuthor(authors),
+    'lastName',
+    '',
+  )}`,
+}))(AuthorReply)
+
+// #region styles
+const Root = styled.div`
+  background-color: ${th('colorBackgroundHue')};
+  border: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBackgroundHue3')};
+  border-radius: ${th('borderRadius')};
+  padding: calc(${th('gridUnit')} * 2);
+  margin: ${th('gridUnit')};
+`
+// #endregion
diff --git a/packages/component-faraday-ui/src/AuthorReply.md b/packages/component-faraday-ui/src/AuthorReply.md
new file mode 100644
index 0000000000000000000000000000000000000000..0548cdd8dc8e29ab92e88edc197301ea6b7b3eb5
--- /dev/null
+++ b/packages/component-faraday-ui/src/AuthorReply.md
@@ -0,0 +1,77 @@
+Reviewer report.
+
+```js
+const fragment = {
+  "id": "1378b0e4-5c29-46a6-8afe-2f5ec1b13899",
+  "type": "fragment",
+  "files": {
+    "manuscripts": [
+      {
+        "id": "e891d6dd-fe46-472d-87db-5c80fdd48ac2/9e103d6a-dd0e-4d1e-b6ff-9b8383579649",
+        "name": "Evolutionary Programming.pdf",
+        "size": 81618,
+        "originalName": "Evolutionary Programming.pdf"
+      }
+    ],
+    "supplementary": []
+  },
+  "owners": [
+    {
+      "id": "f3a16660-ae1e-4ab2-9ae4-220a0c7ac575",
+      "username": "tania.fecheta+a@thinslices.com"
+    }
+  ],
+  "authors": [
+    {
+      "id": "f3a16660-ae1e-4ab2-9ae4-220a0c7ac575",
+      "title": "mrs",
+      "country": "AL",
+      "lastName": "Tania",
+      "firstName": "Author",
+      "affiliation": "Ts",
+      "isSubmitting": true,
+      "isCorresponding": true
+    }
+  ],
+  "created": "2018-10-30T07:33:26.128Z",
+  "version": 2,
+  "metadata": {
+    "type": "research",
+    "title": "Major revision and new version sunmited",
+    "journal": "Bioinorganic Chemistry and Applications",
+    "abstract": "something something"
+  },
+  "conflicts": {
+    "hasFunding": "",
+    "hasConflicts": "no",
+    "hasDataAvailability": ""
+  },
+  "submitted": 1540884806175,
+  "invitations": [
+    {
+      "id": "7b50667d-883c-43d4-aea5-71455e251801",
+      "role": "reviewer",
+      "type": "invitation",
+      "userId": "b7554926-89dc-4b8b-b4d7-cd1bcc51f2de",
+      "hasAnswer": true,
+      "invitedOn": 1540884401711,
+      "isAccepted": true,
+      "respondedOn": 1540884410543
+    }
+  ],
+  "collectionId": "383a5314-788c-49e5-aa00-617426b5c7c7",
+  "declarations": {
+    "agree": true
+  },
+  "fragmentType": "version",
+  "responseToReviewers": {
+    "file": null,
+    "content": "i changed that thing"
+  },
+  "recommendations": []
+};
+
+<AuthorReply
+  fragment={fragment}
+/>
+```
diff --git a/packages/component-faraday-ui/src/ManuscriptCard.js b/packages/component-faraday-ui/src/ManuscriptCard.js
index ae360b12e7ae2b3220528f7e771b5cac322bd377..17e9e176354403406b6066cf5b09f589a9a93cfa 100644
--- a/packages/component-faraday-ui/src/ManuscriptCard.js
+++ b/packages/component-faraday-ui/src/ManuscriptCard.js
@@ -24,6 +24,7 @@ import { OpenModal } from './modals'
 const ManuscriptCard = ({
   onDelete,
   canDelete,
+  isFetching,
   onCardClick,
   canViewReports,
   fragment = {},
@@ -87,16 +88,17 @@ const ManuscriptCard = ({
             <Item justify="flex-end" onClick={e => e.stopPropagation()}>
               <OpenModal
                 confirmText="Delete"
+                isFetching={isFetching}
                 modalKey={`delete-${collId}`}
                 onConfirm={onDelete}
                 title="Are you sure you want to delete this submission?"
               >
-                {onClickEvent => (
+                {showModal => (
                   <ActionLink
+                    height={16}
                     icon="trash"
-                    onClick={onClickEvent}
+                    onClick={showModal}
                     size="small"
-                    style={{ height: 16 }}
                   >
                     Delete
                   </ActionLink>
diff --git a/packages/component-faraday-ui/src/ReviewerReportAuthor.js b/packages/component-faraday-ui/src/ReviewerReportAuthor.js
index 297653497f8a77be8c9bf20135ca64c7c21a54a4..4df5745b8ce86a109bad547466f3fe5ff57f94de 100644
--- a/packages/component-faraday-ui/src/ReviewerReportAuthor.js
+++ b/packages/component-faraday-ui/src/ReviewerReportAuthor.js
@@ -1,16 +1,24 @@
 import React, { Fragment } from 'react'
 import { get } from 'lodash'
-import { withProps } from 'recompose'
+import { withProps, compose } from 'recompose'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { DateParser } from '@pubsweet/ui'
 
-import { Label, Item, FileItem, Row, Text } from './'
+import {
+  Label,
+  Item,
+  FileItem,
+  Row,
+  Text,
+  withFilePreview,
+  withFileDownload,
+} from './'
 
 const ReviewerReportAuthor = ({
-  onPreview,
-  onDownload,
   reviewFile,
+  previewFile,
+  downloadFile,
   publicReport,
   reviewerName,
   reviewerIndex,
@@ -45,8 +53,8 @@ const ReviewerReportAuthor = ({
           <Item flex={0} mr={1}>
             <FileItem
               item={reviewFile}
-              onDownload={onDownload}
-              onPreview={onPreview}
+              onDownload={downloadFile}
+              onPreview={previewFile}
             />
           </Item>
         </Row>
@@ -55,20 +63,24 @@ const ReviewerReportAuthor = ({
   </Root>
 )
 
-export default withProps(({ report, journal: { recommendations = [] } }) => ({
-  recommendation: get(
-    recommendations.find(r => r.value === report.recommendation),
-    'label',
-  ),
-  reviewFile: get(report, 'comments.0.files.0'),
-  publicReport: get(report, 'comments.0.content'),
-  reviewerName: `${get(report, 'reviewer.firstName', '')} ${get(
-    report,
-    'reviewer.lastName',
-    '',
-  )}`,
-  reviewerIndex: get(report, 'reviewerIndex', ''),
-}))(ReviewerReportAuthor)
+export default compose(
+  withFilePreview,
+  withFileDownload,
+  withProps(({ report, journal: { recommendations = [] } }) => ({
+    recommendation: get(
+      recommendations.find(r => r.value === report.recommendation),
+      'label',
+    ),
+    reviewFile: get(report, 'comments.0.files.0'),
+    publicReport: get(report, 'comments.0.content'),
+    reviewerName: `${get(report, 'reviewer.firstName', '')} ${get(
+      report,
+      'reviewer.lastName',
+      '',
+    )}`,
+    reviewerIndex: get(report, 'reviewerIndex', ''),
+  })),
+)(ReviewerReportAuthor)
 
 // #region styles
 const Root = styled.div`
diff --git a/packages/component-faraday-ui/src/Tag.js b/packages/component-faraday-ui/src/Tag.js
index 856a69c88fb0f25ed6a64ed3368221239d961d81..fd6ce0316577b29f1ca95619cdd180a860209c54 100644
--- a/packages/component-faraday-ui/src/Tag.js
+++ b/packages/component-faraday-ui/src/Tag.js
@@ -1,27 +1,41 @@
-import styled, { css } from 'styled-components'
+import { has } from 'lodash'
 import { th } from '@pubsweet/ui-toolkit'
+import styled, { css } from 'styled-components'
 
 import { marginHelper } from './styledHelpers'
 
-export const tagCSS = ({ status }) =>
-  status
-    ? css`
-        padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')};
-        height: 24px;
-        font-family: ${th('fontHeading')};
-      `
-    : css`
-        height: 14px;
-        font-size: 85%;
-        padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px;
-        margin-right: 1px;
-        font-family: ${th('fontInterface')};
-      `
+const tagCSS = props => {
+  if (has(props, 'oldStatus')) {
+    return css`
+      background-color: ${th('colorFurnitureHue')};
+      height: calc(${th('gridUnit')} * 3)
+      font-weight: ${th('tag.fontWeight')};
+      padding: calc(${th('gridUnit')} / 2) ${th('gridUnit')} 0px
+        ${th('gridUnit')};
+    `
+  }
+
+  if (has(props, `status`)) {
+    return css`
+      background-color: ${th('tag.statusBackgroundColor')};
+      padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')};
+      height: 24px;
+      font-family: ${th('fontHeading')};
+    `
+  }
+
+  return css`
+    background-color: ${th('tag.backgroundColor')};
+    height: 14px;
+    font-size: 85%;
+    padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px;
+    margin-right: 1px;
+    font-family: ${th('fontInterface')};
+  `
+}
 
 /** @component */
 export default styled.div`
-  background-color: ${({ status }) =>
-    status ? th('tag.statusBackgroundColor') : th('tag.backgroundColor')};
   border-radius: ${th('tag.borderRadius')
     ? th('tag.borderRadius')
     : th('borderRadius')};
diff --git a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
index 105b76fc04c6a4046c794398157ee770135ad538..5518b3ebfa9c3803816c871f4f8b32b717c468d3 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js
@@ -15,7 +15,14 @@ const SubmittedReportsNumberForAuthorReviews = ({ reports }) => (
   </Row>
 )
 
-const AuthorReviews = ({ invitations, journal, reports, fragment }) =>
+const AuthorReviews = ({
+  invitations,
+  journal,
+  reports,
+  fragment,
+  token,
+  getSignedUrl,
+}) =>
   reports.length > 0 && (
     <ContextualBox
       label="Reviewer Reports"
@@ -24,11 +31,13 @@ const AuthorReviews = ({ invitations, journal, reports, fragment }) =>
         <SubmittedReportsNumberForAuthorReviews reports={reports.length} />
       }
     >
-      {reports.map((r, i) => (
+      {reports.map(r => (
         <ReviewerReportAuthor
+          getSignedUrl={getSignedUrl}
           journal={journal}
           key={r.id}
-          report={reports[i]}
+          report={r}
+          token={token}
         />
       ))}
     </ContextualBox>
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js
new file mode 100644
index 0000000000000000000000000000000000000000..4d3d4b181d864cd2b5c829ad06902b058a3c09ec
--- /dev/null
+++ b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js
@@ -0,0 +1,21 @@
+import React from 'react'
+
+import { ContextualBox, AuthorReply } from '../'
+
+const ResponseToRevisionRequest = ({
+  fragment,
+  authorReply,
+  toggle,
+  expanded,
+}) => (
+  <ContextualBox
+    expanded={expanded}
+    label="Response to Revision Request"
+    mb={2}
+    toggle={toggle}
+  >
+    <AuthorReply fragment={fragment} reply={authorReply} />
+  </ContextualBox>
+)
+
+export default ResponseToRevisionRequest
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.md b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.md
new file mode 100644
index 0000000000000000000000000000000000000000..eae07412e44fa24ea983e46dffd6ca01bef3713b
--- /dev/null
+++ b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.md
@@ -0,0 +1,75 @@
+ResponseToRevisionRequest.
+
+```js
+const fragment = {
+  "id": "1378b0e4-5c29-46a6-8afe-2f5ec1b13899",
+  "type": "fragment",
+  "files": {
+    "manuscripts": [
+      {
+        "id": "e891d6dd-fe46-472d-87db-5c80fdd48ac2/9e103d6a-dd0e-4d1e-b6ff-9b8383579649",
+        "name": "Evolutionary Programming.pdf",
+        "size": 81618,
+        "originalName": "Evolutionary Programming.pdf"
+      }
+    ],
+    "supplementary": []
+  },
+  "owners": [
+    {
+      "id": "f3a16660-ae1e-4ab2-9ae4-220a0c7ac575",
+      "username": "tania.fecheta+a@thinslices.com"
+    }
+  ],
+  "authors": [
+    {
+      "id": "f3a16660-ae1e-4ab2-9ae4-220a0c7ac575",
+      "title": "mrs",
+      "country": "AL",
+      "lastName": "Tania",
+      "firstName": "Author",
+      "affiliation": "Ts",
+      "isSubmitting": true,
+      "isCorresponding": true
+    }
+  ],
+  "created": "2018-10-30T07:33:26.128Z",
+  "version": 2,
+  "metadata": {
+    "type": "research",
+    "title": "Major revision and new version sunmited",
+    "journal": "Bioinorganic Chemistry and Applications",
+    "abstract": "something something"
+  },
+  "conflicts": {
+    "hasFunding": "",
+    "hasConflicts": "no",
+    "hasDataAvailability": ""
+  },
+  "submitted": 1540884806175,
+  "invitations": [
+    {
+      "id": "7b50667d-883c-43d4-aea5-71455e251801",
+      "role": "reviewer",
+      "type": "invitation",
+      "userId": "b7554926-89dc-4b8b-b4d7-cd1bcc51f2de",
+      "hasAnswer": true,
+      "invitedOn": 1540884401711,
+      "isAccepted": true,
+      "respondedOn": 1540884410543
+    }
+  ],
+  "collectionId": "383a5314-788c-49e5-aa00-617426b5c7c7",
+  "declarations": {
+    "agree": true
+  },
+  "fragmentType": "version",
+  "responseToReviewers": {
+    "file": null,
+    "content": "i changed that thing"
+  },
+  "recommendations": []
+};
+
+<ResponseToRevisionRequest fragment={fragment} />
+```
diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
index efa929afe32fd35476948eca48e366414aaa3c15..d8a41b821abe0639bbb6f9cfbe6ffe17b9f75189 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js
@@ -40,6 +40,7 @@ const ReviewerDetails = ({
   highlight,
   canViewReviewersDetails,
   authorCanViewReportsDetails,
+  isLatestVersion,
   ...rest
 }) => (
   <ContextualBox
@@ -62,17 +63,18 @@ const ReviewerDetails = ({
             >
               <H4>Reviewer Details</H4>
             </TabButton>
-            {canInviteReviewers && (
-              <TabButton
-                data-test-id="reviewer-tab-suggestions"
-                ml={1}
-                mr={1}
-                onClick={() => changeTab(2)}
-                selected={selectedTab === 2}
-              >
-                <H4>Reviewer Suggestions</H4>
-              </TabButton>
-            )}
+            {canInviteReviewers &&
+              isLatestVersion && (
+                <TabButton
+                  data-test-id="reviewer-tab-suggestions"
+                  ml={1}
+                  mr={1}
+                  onClick={() => changeTab(2)}
+                  selected={selectedTab === 2}
+                >
+                  <H4>Reviewer Suggestions</H4>
+                </TabButton>
+              )}
             <TabButton
               data-test-id="reviewer-tab-reports"
               ml={1}
@@ -87,12 +89,13 @@ const ReviewerDetails = ({
           <TabContent>
             {selectedTab === 0 && (
               <Fragment>
-                {canInviteReviewers && (
-                  <InviteReviewers
-                    modalKey="invite-reviewers"
-                    onInvite={onInviteReviewer}
-                  />
-                )}
+                {canInviteReviewers &&
+                  isLatestVersion && (
+                    <InviteReviewers
+                      modalKey="invite-reviewers"
+                      onInvite={onInviteReviewer}
+                    />
+                  )}
 
                 <ReviewersTable
                   invitations={invitations}
@@ -101,14 +104,15 @@ const ReviewerDetails = ({
                 />
               </Fragment>
             )}
-            {selectedTab === 2 && (
-              <PublonsTable
-                onInvite={onInvitePublonReviewer}
-                publonsError={fetchingError}
-                publonsFetching={isFetching}
-                reviewers={publonReviewers}
-              />
-            )}
+            {selectedTab === 2 &&
+              isLatestVersion && (
+                <PublonsTable
+                  onInvite={onInvitePublonReviewer}
+                  publonsError={fetchingError}
+                  publonsFetching={isFetching}
+                  reviewers={publonReviewers}
+                />
+              )}
             {selectedTab === 1 && (
               <Fragment>
                 {reports.length === 0 && (
diff --git a/packages/component-faraday-ui/src/contextualBoxes/index.js b/packages/component-faraday-ui/src/contextualBoxes/index.js
index d3ad70c5ba82387ff832effb11447534d18e4b15..97a41d51e4791b8f11f3d53cbd355de93d516cd8 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/index.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/index.js
@@ -3,3 +3,6 @@ export { default as ReviewerDetails } from './ReviewerDetails'
 export { default as HERecommendation } from './HERecommendation'
 export { default as ReviewerReportForm } from './ReviewerReportForm'
 export { default as AuthorReviews } from './AuthorReviews'
+export {
+  default as ResponseToRevisionRequest,
+} from './ResponseToRevisionRequest'
diff --git a/packages/component-faraday-ui/src/index.js b/packages/component-faraday-ui/src/index.js
index 4bfa4af165b2ecd8865299970a1ebe90428a1cfb..a99b60e4c1b2e18f15810beb84255aecd4ad4260 100644
--- a/packages/component-faraday-ui/src/index.js
+++ b/packages/component-faraday-ui/src/index.js
@@ -6,6 +6,7 @@ export * from './gridItems'
 
 export { default as ActionLink } from './ActionLink'
 export { default as AuthorWithTooltip } from './AuthorWithTooltip'
+export { default as AuthorReply } from './AuthorReply'
 export { default as Logo } from './Logo'
 export { default as AppBar } from './AppBar'
 export { default as AppBarMenu } from './AppBarMenu'
diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
index b7e6f5389f196f87344e2b5f35a2f0630117c644..f93e6c4c396f67836c8d1142000cc05682aac647 100644
--- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
+++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
@@ -23,6 +23,7 @@ const ManuscriptHeader = ({
   manuscriptType = {},
   editorInChief = 'Unassigned',
   collection: { visibleStatus = 'Draft', customId, handlingEditor },
+  isLatestVersion,
 }) => {
   const { authors = [], metadata = {}, submitted = null } = fragment
   const { title = 'No title', journal = '', type = '' } = metadata
@@ -34,9 +35,13 @@ const ManuscriptHeader = ({
         justify="space-between"
       >
         <H2 mb={1}>{title}</H2>
-        <Tag data-test-id="fragment-status" status>
-          {visibleStatus}
-        </Tag>
+        {isLatestVersion ? (
+          <Tag data-test-id="fragment-status" status>
+            {visibleStatus}
+          </Tag>
+        ) : (
+          <Tag oldStatus>Viewing an Older Version</Tag>
+        )}
       </Row>
       {authors.length > 0 && (
         <Row
diff --git a/packages/component-fixture-manager/src/fixtures/collectionIDs.js b/packages/component-fixture-manager/src/fixtures/collectionIDs.js
index d4d27580eba01b480a3de9ec5650fc7a0dcc8b01..4f351142bab1ef0de0b4c1d82f767ed391b42b75 100644
--- a/packages/component-fixture-manager/src/fixtures/collectionIDs.js
+++ b/packages/component-fixture-manager/src/fixtures/collectionIDs.js
@@ -5,4 +5,5 @@ const chance = new Chance()
 module.exports = {
   standardCollID: chance.guid(),
   collectionReviewCompletedID: chance.guid(),
+  twoVersionsCollectionId: chance.guid(),
 }
diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js
index 4984c9f078027f840f262f68a5fd22b914b87cbf..f6bb11aaa73ff13cf739b921e31910b2eaba35e5 100644
--- a/packages/component-fixture-manager/src/fixtures/collections.js
+++ b/packages/component-fixture-manager/src/fixtures/collections.js
@@ -4,12 +4,14 @@ const { fragment, reviewCompletedFragment } = require('./fragments')
 const {
   standardCollID,
   collectionReviewCompletedID,
+  twoVersionsCollectionId,
 } = require('./collectionIDs')
 
 const chance = new Chance()
 const collections = {
   collection: {
     id: standardCollID,
+    delete: jest.fn(),
     title: chance.sentence(),
     type: 'collection',
     fragments: [fragment.id],
@@ -52,6 +54,7 @@ const collections = {
   },
   collection1: {
     id: standardCollID,
+    delete: jest.fn(),
     title: chance.sentence(),
     type: 'collection',
     fragments: [fragment.id],
@@ -94,6 +97,7 @@ const collections = {
   },
   collectionReviewCompleted: {
     id: collectionReviewCompletedID,
+    delete: jest.fn(),
     type: 'collection',
     owners: [user.id],
     status: 'reviewCompleted',
@@ -123,6 +127,36 @@ const collections = {
     },
     technicalChecks: {},
   },
+  twoVersionsCollection: {
+    id: twoVersionsCollectionId,
+    title: chance.sentence(),
+    type: 'collection',
+    fragments: [fragment.id, reviewCompletedFragment.id],
+    owners: [user.id],
+    save: jest.fn(() => collections.collection),
+    invitations: [
+      {
+        id: chance.guid(),
+        role: 'handlingEditor',
+        hasAnswer: true,
+        isAccepted: false,
+        userId: handlingEditor.id,
+        invitedOn: chance.timestamp(),
+        respondedOn: null,
+      },
+    ],
+    handlingEditor: {
+      id: handlingEditor.id,
+      hasAnswer: false,
+      isAccepted: false,
+      email: handlingEditor.email,
+      invitedOn: chance.timestamp(),
+      respondedOn: null,
+      name: `${handlingEditor.firstName} ${handlingEditor.lastName}`,
+    },
+    status: 'revisionRequested',
+    customId: chance.natural({ min: 999999, max: 9999999 }),
+  },
 }
 
 module.exports = collections
diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js
index c8931dd9bb71a0259f0817a5a0a448ea53e37e42..5696e17019b802e9a131c762b184f058f2bc799e 100644
--- a/packages/component-fixture-manager/src/fixtures/fragments.js
+++ b/packages/component-fixture-manager/src/fixtures/fragments.js
@@ -18,6 +18,12 @@ const chance = new Chance()
 const fragments = {
   fragment: {
     id: chance.guid(),
+    delete: jest.fn(),
+    files: {
+      manuscripts: [{ id: chance.guid() }],
+      coverLetter: [],
+      supplementary: [],
+    },
     collectionId: standardCollID,
     metadata: {
       title: chance.sentence(),
@@ -180,6 +186,12 @@ const fragments = {
   },
   noParentFragment: {
     id: chance.guid(),
+    delete: jest.fn(),
+    files: {
+      manuscripts: [{ id: chance.guid() }],
+      coverLetter: [],
+      supplementary: [],
+    },
     collectionId: '',
     metadata: {
       title: chance.sentence(),
@@ -199,9 +211,9 @@ const fragments = {
   },
   reviewCompletedFragment: {
     id: chance.guid(),
+    delete: jest.fn(),
     type: 'fragment',
     files: {
-      coverLetter: [],
       manuscripts: [
         {
           id:
@@ -211,6 +223,7 @@ const fragments = {
           originalName: 'LinkedInProfileDemystified.pdf',
         },
       ],
+      coverLetter: [],
       supplementary: [],
     },
     owners: [user.id],
diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js
index 5191421c22e3cd9f0f4c5256c18becd8c6d89166..c100c2a3798fc3bc4e635a98077806f11ad86bcc 100644
--- a/packages/component-fixture-manager/src/fixtures/teams.js
+++ b/packages/component-fixture-manager/src/fixtures/teams.js
@@ -33,6 +33,7 @@ const teams = {
     },
     members: [handlingEditor.id],
     save: jest.fn(() => teams.heTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.heTeam),
     id: heTeamID,
   },
@@ -49,6 +50,7 @@ const teams = {
     },
     members: [reviewer.id, inactiveReviewer.id, answerReviewer.id],
     save: jest.fn(() => teams.revTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.revTeam),
     id: revTeamID,
   },
@@ -65,6 +67,7 @@ const teams = {
     },
     members: [reviewer.id, answerReviewer.id, recReviewer.id],
     save: jest.fn(() => teams.revRecommendationTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.revRecommendationTeam),
     id: revRecommendationTeamID,
   },
@@ -81,6 +84,7 @@ const teams = {
     },
     members: [submittingAuthor.id],
     save: jest.fn(() => teams.authorTeam),
+    delete: jest.fn(),
     updateProperties: jest.fn(() => teams.authorTeam),
     id: authorTeamID,
   },
diff --git a/packages/component-helper-service/src/services/Fragment.js b/packages/component-helper-service/src/services/Fragment.js
index 174067efdfe0cbb7e7e7f627f5a8fd53884bd7f0..4b9e5edd4fefe8c3864698ba2ea205be4c3ecbac 100644
--- a/packages/component-helper-service/src/services/Fragment.js
+++ b/packages/component-helper-service/src/services/Fragment.js
@@ -1,4 +1,4 @@
-const get = require('lodash/get')
+const { get, remove } = require('lodash')
 const User = require('./User')
 
 class Fragment {
@@ -92,14 +92,14 @@ class Fragment {
 
   getInvitations({ isAccepted = true, role = 'reviewer', type }) {
     const { fragment: { invitations = [], recommendations = [] } } = this
-    let filteredInvitations = isAccepted
+    const filteredInvitations = isAccepted
       ? invitations.filter(
           inv => inv.role === role && inv.hasAnswer && inv.isAccepted,
         )
       : invitations.filter(inv => inv.role === role && !inv.hasAnswer)
 
     if (type === 'submitted') {
-      filteredInvitations = filteredInvitations.filter(inv =>
+      return filteredInvitations.filter(inv =>
         recommendations.find(
           rec =>
             rec.recommendationType === 'review' &&
@@ -108,12 +108,11 @@ class Fragment {
         ),
       )
     } else if (type === 'accepted') {
-      filteredInvitations = filteredInvitations.filter(inv =>
-        recommendations.find(
-          rec =>
-            rec.recommendationType === 'review' && inv.userId !== rec.userId,
-        ),
-      )
+      recommendations.forEach(rec => {
+        if (rec.recommendationType === 'review' && rec.submittedOn) {
+          remove(filteredInvitations, inv => inv.userId === rec.userId)
+        }
+      })
     }
 
     return filteredInvitations
diff --git a/packages/component-helper-service/src/services/Team.js b/packages/component-helper-service/src/services/Team.js
index dd3050ebddd07abe3bf447ecea75676ca0ebd3e2..631bd09291af51bdacb90ec2978b374a1c672511 100644
--- a/packages/component-helper-service/src/services/Team.js
+++ b/packages/component-helper-service/src/services/Team.js
@@ -130,6 +130,15 @@ class Team {
     )
   }
 
+  async getTeams(objectType) {
+    const { TeamModel, fragmentId, collectionId } = this
+    const objectId = objectType === 'collection' ? collectionId : fragmentId
+    const teams = await TeamModel.all()
+    return teams.filter(
+      team => team.object.type === objectType && team.object.id === objectId,
+    )
+  }
+
   async deleteHandlingEditor({ collection, role, user }) {
     const team = await this.getTeam({
       role,
diff --git a/packages/component-helper-service/src/tests/fragment.test.js b/packages/component-helper-service/src/tests/fragment.test.js
index 3b5875eaf284e315ce1e3dd8a8792769e545e9c4..61e86748001df9b64466c7ed461bd1cf0c27c918 100644
--- a/packages/component-helper-service/src/tests/fragment.test.js
+++ b/packages/component-helper-service/src/tests/fragment.test.js
@@ -3,27 +3,238 @@ process.env.SUPPRESS_NO_CONFIG_WARNING = true
 
 const { cloneDeep } = require('lodash')
 const fixturesService = require('pubsweet-component-fixture-service')
+const Chance = require('chance')
 
+const chance = new Chance()
 const { fixtures } = fixturesService
 const { Fragment } = require('../Helper')
 
+const acceptedReviewerId = chance.guid()
+const submittedReviewerId1 = chance.guid()
+const submittedReviewerId2 = chance.guid()
+const fragment = {
+  invitations: [
+    {
+      id: chance.guid(),
+      role: 'reviewer',
+      hasAnswer: true,
+      isAccepted: true,
+      userId: acceptedReviewerId,
+      invitedOn: chance.timestamp(),
+      respondedOn: chance.timestamp(),
+      type: 'invitation',
+    },
+    {
+      id: chance.guid(),
+      role: 'reviewer',
+      hasAnswer: true,
+      isAccepted: true,
+      userId: submittedReviewerId1,
+      invitedOn: chance.timestamp(),
+      respondedOn: chance.timestamp(),
+      type: 'invitation',
+    },
+    {
+      id: chance.guid(),
+      role: 'reviewer',
+      hasAnswer: true,
+      isAccepted: true,
+      userId: submittedReviewerId2,
+      invitedOn: chance.timestamp(),
+      respondedOn: chance.timestamp(),
+      type: 'invitation',
+    },
+  ],
+  recommendations: [
+    {
+      recommendation: 'publish',
+      recommendationType: 'review',
+      comments: [
+        {
+          content: chance.paragraph(),
+          public: chance.bool(),
+          files: [
+            {
+              id: chance.guid(),
+              name: 'file.pdf',
+              size: chance.natural(),
+            },
+          ],
+        },
+      ],
+      id: chance.guid(),
+      userId: submittedReviewerId1,
+      createdOn: chance.timestamp(),
+      updatedOn: chance.timestamp(),
+      submittedOn: chance.timestamp(),
+    },
+    {
+      recommendation: 'publish',
+      recommendationType: 'review',
+      comments: [
+        {
+          content: chance.paragraph(),
+          public: chance.bool(),
+          files: [
+            {
+              id: chance.guid(),
+              name: 'file.pdf',
+              size: chance.natural(),
+            },
+          ],
+        },
+      ],
+      id: chance.guid(),
+      userId: submittedReviewerId2,
+      createdOn: chance.timestamp(),
+      updatedOn: chance.timestamp(),
+      submittedOn: chance.timestamp(),
+    },
+    {
+      recommendation: 'publish',
+      recommendationType: 'review',
+      comments: [
+        {
+          content: chance.paragraph(),
+          public: chance.bool(),
+          files: [
+            {
+              id: chance.guid(),
+              name: 'file.pdf',
+              size: chance.natural(),
+            },
+          ],
+        },
+      ],
+      id: chance.guid(),
+      userId: acceptedReviewerId,
+      createdOn: chance.timestamp(),
+      updatedOn: chance.timestamp(),
+    },
+  ],
+}
+
 describe('Fragment helper', () => {
   let testFixtures = {}
+  let testFragment = {}
   beforeEach(() => {
     testFixtures = cloneDeep(fixtures)
+    testFragment = cloneDeep(fragment)
   })
 
-  it('hasReviewReport - should return true if the fragment has a review report', () => {
-    const { fragment } = testFixtures.fragments
-    const fragmentHelper = new Fragment({ fragment })
+  describe('hasReviewReport', () => {
+    it('should return true if the fragment has a review report', () => {
+      const { fragment } = testFixtures.fragments
+      const fragmentHelper = new Fragment({ fragment })
+
+      expect(fragmentHelper.hasReviewReport()).toBeTruthy()
+    })
+    it('should return false if the fragment does not have a review report', () => {
+      const { fragment } = testFixtures.fragments
+      fragment.recommendations = []
+      const fragmentHelper = new Fragment({ fragment })
 
-    expect(fragmentHelper.hasReviewReport()).toBeTruthy()
+      expect(fragmentHelper.hasReviewReport()).toBeFalsy()
+    })
   })
-  it('hasReviewReport - should return false if the fragment does not have a review report', () => {
-    const { fragment } = testFixtures.fragments
-    fragment.recommendations = []
-    const fragmentHelper = new Fragment({ fragment })
 
-    expect(fragmentHelper.hasReviewReport()).toBeFalsy()
+  describe('getInvitations', () => {
+    it('should return accepted invitations if type is accepted and a review report has been started', () => {
+      const fragmentHelper = new Fragment({ fragment: testFragment })
+
+      const acceptedInvitations = fragmentHelper.getInvitations({
+        isAccepted: true,
+        type: 'accepted',
+      })
+
+      expect(acceptedInvitations).toHaveLength(1)
+    })
+    it('should return accepted invitations if type is accepted and no review report has been started', () => {
+      testFragment.recommendations = [
+        {
+          recommendation: 'publish',
+          recommendationType: 'review',
+          comments: [
+            {
+              content: chance.paragraph(),
+              public: chance.bool(),
+              files: [
+                {
+                  id: chance.guid(),
+                  name: 'file.pdf',
+                  size: chance.natural(),
+                },
+              ],
+            },
+          ],
+          id: chance.guid(),
+          userId: submittedReviewerId1,
+          createdOn: chance.timestamp(),
+          updatedOn: chance.timestamp(),
+          submittedOn: chance.timestamp(),
+        },
+        {
+          recommendation: 'publish',
+          recommendationType: 'review',
+          comments: [
+            {
+              content: chance.paragraph(),
+              public: chance.bool(),
+              files: [
+                {
+                  id: chance.guid(),
+                  name: 'file.pdf',
+                  size: chance.natural(),
+                },
+              ],
+            },
+          ],
+          id: chance.guid(),
+          userId: submittedReviewerId2,
+          createdOn: chance.timestamp(),
+          updatedOn: chance.timestamp(),
+          submittedOn: chance.timestamp(),
+        },
+      ]
+
+      const fragmentHelper = new Fragment({ fragment: testFragment })
+
+      const acceptedInvitations = fragmentHelper.getInvitations({
+        isAccepted: true,
+        type: 'accepted',
+      })
+
+      expect(acceptedInvitations).toHaveLength(1)
+    })
+    it('should return invitations of submitted reviewers if type is submitted', () => {
+      const fragmentHelper = new Fragment({ fragment: testFragment })
+
+      const submittedInvitations = fragmentHelper.getInvitations({
+        isAccepted: true,
+        type: 'submitted',
+      })
+
+      expect(submittedInvitations).toHaveLength(2)
+    })
+    it('should return invitations of pending reviewers if type is pending and isAccepted is false', () => {
+      testFragment.invitations.push({
+        id: chance.guid(),
+        role: 'reviewer',
+        hasAnswer: false,
+        isAccepted: false,
+        userId: chance.guid(),
+        invitedOn: chance.timestamp(),
+        respondedOn: chance.timestamp(),
+        type: 'invitation',
+      })
+      const fragmentHelper = new Fragment({ fragment: testFragment })
+
+      const pendingInvitations = fragmentHelper.getInvitations({
+        isAccepted: false,
+        type: 'pending',
+      })
+
+      expect(pendingInvitations).toHaveLength(1)
+    })
   })
 })
diff --git a/packages/component-invite/src/routes/fragmentsInvitations/post.js b/packages/component-invite/src/routes/fragmentsInvitations/post.js
index 2eab3d2d1642e1aed6f2a9384bbf11b9058fd993..4442ae74c8b94459864bd373d114056d06dfd09c 100644
--- a/packages/component-invite/src/routes/fragmentsInvitations/post.js
+++ b/packages/component-invite/src/routes/fragmentsInvitations/post.js
@@ -11,6 +11,8 @@ const {
 
 const emailInvitations = require('./emails/invitations')
 
+const { last } = require('lodash')
+
 module.exports = models => async (req, res) => {
   const { email, role } = req.body
 
@@ -40,6 +42,10 @@ module.exports = models => async (req, res) => {
       return res.status(400).json({
         error: `Fragment ${fragmentId} does not match collection ${collectionId}.`,
       })
+    if (last(collection.fragments) !== fragmentId)
+      return res.status(400).json({
+        error: `Fragment ${fragmentId} is an older version.`,
+      })
     fragment = await models.Fragment.find(fragmentId)
   } catch (e) {
     const notFoundError = await services.handleNotFoundError(e, 'item')
diff --git a/packages/component-manuscript-manager/src/Collections.js b/packages/component-manuscript-manager/src/Collections.js
index 8ce7c79779abb552a2728ad835b3e078d21ccaa8..81f8c4d7f6977ae496a3d021ac6dbc0a7be37dca 100644
--- a/packages/component-manuscript-manager/src/Collections.js
+++ b/packages/component-manuscript-manager/src/Collections.js
@@ -7,8 +7,8 @@ const Collections = app => {
     session: false,
   })
   /**
-   * @api {get} /api/fragments Get latest fragments
-   * @apiGroup Fragments
+   * @api {get} /api/collections Get latest collections
+   * @apiGroup Collections
    * @apiSuccessExample {json} Success
    *    HTTP/1.1 200 OK
    *    [
@@ -28,7 +28,7 @@ const Collections = app => {
    *        }
    *      }
    *    ]
-   * @apiErrorExample {json} Get fragments errors
+   * @apiErrorExample {json} Get collections errors
    *    HTTP/1.1 403 Forbidden
    */
   app.get(
@@ -36,6 +36,20 @@ const Collections = app => {
     authBearer,
     require(`${routePath}/get`)(app.locals.models),
   )
+
+  /**
+   * @api {delete} /api/collections/:collectionId Delete collection with specified id
+   * @apiGroup Collections
+   * @apiSuccessExample {json} Success
+   *    HTTP/1.1 204 Accepted
+   * @apiErrorExample {json} Get collections errors
+   *    HTTP/1.1 403 Forbidden
+   */
+  app.delete(
+    '/api/collections/:collectionId',
+    authBearer,
+    require(`${routePath}/delete`)(app.locals.models),
+  )
 }
 
 module.exports = Collections
diff --git a/packages/component-manuscript-manager/src/routes/collections/delete.js b/packages/component-manuscript-manager/src/routes/collections/delete.js
new file mode 100644
index 0000000000000000000000000000000000000000..62ed1fc8c760f3f1c2aa0385e3a0db337dcb8be5
--- /dev/null
+++ b/packages/component-manuscript-manager/src/routes/collections/delete.js
@@ -0,0 +1,85 @@
+const { get, remove, concat, has } = require('lodash')
+const config = require('config')
+
+const {
+  Team,
+  services,
+  authsome: authsomeHelper,
+} = require('pubsweet-component-helper-service')
+
+const {
+  deleteFilesS3,
+} = require('pubsweet-component-mts-package/src/PackageManager')
+
+const s3Config = get(config, 'pubsweet-component-aws-s3', {})
+
+module.exports = models => async (req, res) => {
+  const { collectionId } = req.params
+  let collection, fragment
+  try {
+    collection = await models.Collection.find(collectionId)
+
+    if (has(collection, 'status')) {
+      return res.status(400).json({
+        error: 'You can only delete manuscripts while in draft.',
+      })
+    }
+
+    const fragmentId = collection.fragments[0]
+    fragment = await models.Fragment.find(fragmentId)
+
+    const authsome = authsomeHelper.getAuthsome(models)
+
+    const canDelete = await authsome.can(req.user, 'DELETE', collection)
+    if (!canDelete)
+      return res.status(403).json({
+        error: 'Unauthorized.',
+      })
+
+    const teamHelper = new Team({
+      TeamModel: models.Team,
+      fragmentId,
+      collectionId,
+    })
+    const teams = await teamHelper.getTeams('fragment')
+
+    await Promise.all(
+      teams.map(async team => {
+        await Promise.all(
+          team.members.map(async member => {
+            const user = await models.User.find(member)
+
+            remove(user.teams, teamId => teamId === team.id)
+
+            return user.save()
+          }),
+        )
+        return team.delete()
+      }),
+    )
+
+    let fileKeys = concat(
+      fragment.files.manuscripts,
+      fragment.files.coverLetter,
+      fragment.files.supplementary,
+      fragmentId,
+    )
+
+    fileKeys = fileKeys.map(file => file.id)
+
+    if (fileKeys.length > 1) {
+      await deleteFilesS3({ fileKeys, s3Config })
+    }
+
+    await fragment.delete()
+
+    await collection.delete()
+
+    return res.status(204).send()
+  } catch (e) {
+    const notFoundError = await services.handleNotFoundError(e, 'Item')
+    return res.status(notFoundError.status).json({
+      error: notFoundError.message,
+    })
+  }
+}
diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
index 55d54aa4274c9035da2fe92342ccab04929b6220..43206e0e19c9bb85290713f5eb829d04dd700df6 100644
--- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
+++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js
@@ -1,5 +1,5 @@
 const uuid = require('uuid')
-const { pick, get, set, has, isEmpty } = require('lodash')
+const { pick, get, set, has, isEmpty, last } = require('lodash')
 const config = require('config')
 const { v4 } = require('uuid')
 
@@ -69,6 +69,15 @@ module.exports = models => async (req, res) => {
       error: 'Unauthorized.',
     })
 
+  if (
+    recommendationType === recommendations.type.editor &&
+    last(collection.fragments) !== fragmentId
+  ) {
+    return res
+      .status(400)
+      .json({ error: 'Cannot make a recommendation on an older version.' })
+  }
+
   if (
     recommendation === recommendations.publish &&
     recommendationType === recommendations.type.editor &&
diff --git a/packages/component-manuscript-manager/src/tests/collections/delete.test.js b/packages/component-manuscript-manager/src/tests/collections/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..cee28293a8b2143164d5697c09d49d50762200f5
--- /dev/null
+++ b/packages/component-manuscript-manager/src/tests/collections/delete.test.js
@@ -0,0 +1,65 @@
+process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
+process.env.SUPPRESS_NO_CONFIG_WARNING = true
+
+const { cloneDeep } = require('lodash')
+const fixturesService = require('pubsweet-component-fixture-service')
+const requests = require('../requests')
+
+const { Model, fixtures } = fixturesService
+
+jest.mock('pubsweet-component-mts-package/src/PackageManager', () => ({
+  deleteFilesS3: jest.fn(),
+}))
+jest.mock('@pubsweet/component-send-email', () => ({
+  send: jest.fn(),
+}))
+
+const path = '../routes/collections/delete'
+const route = {
+  path: '/api/collections/:collectionId/',
+}
+describe('Delete collections route handler', () => {
+  let testFixtures = {}
+  let models
+  beforeEach(() => {
+    testFixtures = cloneDeep(fixtures)
+    models = Model.build(testFixtures)
+  })
+
+  it('should return an error when deleting a collection which is not in draft', async () => {
+    const { admin } = testFixtures.users
+    const { collection } = testFixtures.collections
+
+    const res = await requests.sendRequest({
+      userId: admin.id,
+      route,
+      models,
+      path,
+      params: {
+        collectionId: collection.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toBe('You can only delete manuscripts while in draft.')
+  })
+
+  it('should return success when deleting a draft collection', async () => {
+    const { admin } = testFixtures.users
+    const { collection } = testFixtures.collections
+    delete collection.status
+
+    const res = await requests.sendRequest({
+      userId: admin.id,
+      route,
+      models,
+      path,
+      params: {
+        collectionId: collection.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(204)
+  })
+})
diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
index b090a9cb6fc1ae464488560f7032b0ff97388dea..867d1ed0d05986fd03e389da064d08e4a19dfc77 100644
--- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
+++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js
@@ -357,4 +357,58 @@ describe('Post fragments recommendations route handler', () => {
       'Cannot publish without at least one reviewer report.',
     )
   })
+
+  it('should return an error when a HE makes a recommendation on an older version of a manuscript', async () => {
+    const { handlingEditor } = testFixtures.users
+    const { twoVersionsCollection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+    body.recommendation = 'publish'
+    body.recommendationType = 'editorRecommendation'
+
+    const res = await requests.sendRequest({
+      body,
+      userId: handlingEditor.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: twoVersionsCollection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+
+    expect(data.error).toEqual(
+      'Cannot make a recommendation on an older version.',
+    )
+  })
+
+  it('should return an error when an EiC makes a decision on an older version of a manuscript', async () => {
+    const { editorInChief } = testFixtures.users
+    const { twoVersionsCollection } = testFixtures.collections
+    const { fragment } = testFixtures.fragments
+    body.recommendation = 'publish'
+    body.recommendationType = 'editorRecommendation'
+
+    const res = await requests.sendRequest({
+      body,
+      userId: editorInChief.id,
+      models,
+      route,
+      path,
+      params: {
+        collectionId: twoVersionsCollection.id,
+        fragmentId: fragment.id,
+      },
+    })
+
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+
+    expect(data.error).toEqual(
+      'Cannot make a recommendation on an older version.',
+    )
+  })
 })
diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js
index ab97d296049c9240213c740f6987eb0cabd8f8ad..e04f5a7ddd225a507a3c9eb85b69de865aa08e0b 100644
--- a/packages/component-manuscript/src/components/ManuscriptLayout.js
+++ b/packages/component-manuscript/src/components/ManuscriptLayout.js
@@ -4,8 +4,9 @@ import { isEmpty, get } from 'lodash'
 import {
   Text,
   paddingHelper,
-  ReviewerDetails,
   AuthorReviews,
+  SubmitRevision,
+  ReviewerDetails,
   HERecommendation,
   ManuscriptHeader,
   ManuscriptAssignHE,
@@ -13,7 +14,7 @@ import {
   ManuscriptDetailsTop,
   ResponseToInvitation,
   ManuscriptEicDecision,
-  SubmitRevision,
+  ResponseToRevisionRequest,
 } from 'pubsweet-component-faraday-ui'
 
 import ReviewerReportCard from './ReviewReportCard'
@@ -49,17 +50,19 @@ const ManuscriptLayout = ({
   heResponseExpanded,
   toggleReviewerResponse,
   invitationsWithReviewers,
+  responseToRevisionRequest,
   publonReviewers,
   reviewerResponseExpanded,
   pendingOwnRecommendation,
   toggleReviewerRecommendations,
   reviewerRecommendationExpanded,
-  shouldReview,
+  authorResponseToRevisonRequest,
   submittedOwnRecommendation,
   reviewerReports,
   reviewerRecommendations,
   toggleReviewerDetails,
   reviewerDetailsExpanded,
+  toggleResponseToRevisionRequest,
   editorialCommentsExpanded,
   toggleEditorialComments,
   submitRevision,
@@ -67,6 +70,7 @@ const ManuscriptLayout = ({
   recommendationHandler,
   inviteHandlingEditor,
   versions,
+  isLatestVersion,
 }) => (
   <Root pb={30}>
     {!isEmpty(collection) && !isEmpty(fragment) ? (
@@ -87,6 +91,7 @@ const ManuscriptLayout = ({
           handlingEditors={handlingEditors}
           inviteHE={toggleAssignHE}
           isFetching={isFetchingData.editorsFetching}
+          isLatestVersion={isLatestVersion}
           journal={journal}
           resendInvitation={inviteHandlingEditor.assignHE}
           revokeInvitation={inviteHandlingEditor.revokeHE}
@@ -112,8 +117,10 @@ const ManuscriptLayout = ({
         {get(currentUser, 'permissions.authorCanViewReportsDetails', false) && (
           <AuthorReviews
             currentUser={currentUser}
+            getSignedUrl={getSignedUrl}
             journal={journal}
             reports={reviewerReports}
+            token={get(currentUser, 'token')}
           />
         )}
 
@@ -126,7 +133,16 @@ const ManuscriptLayout = ({
           />
         )}
 
-        {shouldReview && (
+        {authorResponseToRevisonRequest.content && (
+          <ResponseToRevisionRequest
+            authorReply={authorResponseToRevisonRequest.content}
+            expanded={responseToRevisionRequest}
+            fragment={fragment}
+            toggle={toggleResponseToRevisionRequest}
+          />
+        )}
+
+        {get(currentUser, 'permissions.canReview', false) && (
           <ReviewerReportForm
             changeForm={changeForm}
             expanded={reviewerRecommendationExpanded}
@@ -186,23 +202,26 @@ const ManuscriptLayout = ({
             }
             invitations={invitationsWithReviewers}
             isFetching={isFetchingData.publonsFetching}
+            isLatestVersion={isLatestVersion}
             journal={journal}
             mb={2}
             publonReviewers={publonReviewers}
             reviewerReports={reviewerReports}
             scrollIntoView
             toggle={toggleReviewerDetails}
+            token={get(currentUser, 'token')}
             {...inviteReviewer}
           />
         )}
 
-        {get(currentUser, 'permissions.canSubmitRevision', false) && (
-          <SubmitRevision {...submitRevision} />
-        )}
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canSubmitRevision', false) && (
+            <SubmitRevision {...submitRevision} />
+          )}
 
-        {get(currentUser, 'permissions.canMakeHERecommendation', false) &&
-          (!invitationsWithReviewers.length ||
-            reviewerRecommendations.length > 0) && (
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canMakeHERecommendation', false) &&
+          reviewerRecommendations.length > 0 && (
             <HERecommendation
               formValues={get(formValues, 'editorialRecommendation', {})}
               hasReviewerReports={reviewerRecommendations.length > 0}
@@ -214,16 +233,17 @@ const ManuscriptLayout = ({
             />
           )}
 
-        {get(currentUser, 'permissions.canMakeDecision', false) && (
-          <ManuscriptEicDecision
-            collection={collection}
-            formValues={get(formValues, 'eicDecision')}
-            highlight={editorialRecommendations.length > 0}
-            messagesLabel={messagesLabel}
-            mt={2}
-            submitDecision={recommendationHandler.createRecommendation}
-          />
-        )}
+        {isLatestVersion &&
+          get(currentUser, 'permissions.canMakeDecision', false) && (
+            <ManuscriptEicDecision
+              collection={collection}
+              formValues={get(formValues, 'eicDecision')}
+              highlight={editorialRecommendations.length > 0}
+              messagesLabel={messagesLabel}
+              mt={2}
+              submitDecision={recommendationHandler.createRecommendation}
+            />
+          )}
       </Fragment>
     ) : (
       <Text>Loading...</Text>
diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js
index ab96f5c6b3bb159bf4e1d9f15ea20a341029e5a3..e51afe754d877bef7123805ae4f751fa935d5495 100644
--- a/packages/component-manuscript/src/components/ManuscriptPage.js
+++ b/packages/component-manuscript/src/components/ManuscriptPage.js
@@ -31,6 +31,7 @@ import {
   selectEditorialRecommendations,
 } from 'pubsweet-components-faraday/src/redux/recommendations'
 import {
+  canReview,
   getUserToken,
   currentUserIs,
   canViewReports,
@@ -47,6 +48,7 @@ import {
   canViewReviewersDetails,
   canViewEditorialComments,
   pendingReviewerInvitation,
+  getFragmentAuthorResponse,
   canOverrideTechnicalChecks,
   authorCanViewReportsDetails,
   getOwnPendingRecommendation,
@@ -72,6 +74,7 @@ import {
   redirectToError,
   parseSearchParams,
   getPublonsReviewers,
+  isLatestVersion,
 } from './utils'
 
 import {
@@ -125,6 +128,10 @@ export default compose(
         state,
         match.params.version,
       ),
+      authorResponseToRevisonRequest: getFragmentAuthorResponse(
+        state,
+        match.params.version,
+      ),
     }),
     {
       changeForm,
@@ -160,6 +167,7 @@ export default compose(
         isReviewer: currentUserIsReviewer(state, get(fragment, 'id', '')),
         isHEToManuscript: isHEToManuscript(state, get(collection, 'id', '')),
         permissions: {
+          canReview: canReview(state, collection, fragment),
           canSubmitRevision: canSubmitRevision(state, fragment),
           canMakeHERecommendation: canMakeHERecommendation(state, {
             collection,
@@ -175,7 +183,7 @@ export default compose(
           canInviteReviewers: canInviteReviewers(state, collection),
           canMakeRecommendation: !isUndefined(pendingOwnRecommendation),
           canMakeRevision: canMakeRevision(state, collection, fragment),
-          canMakeDecision: canMakeDecision(state, collection, fragment),
+          canMakeDecision: canMakeDecision(state, collection),
           canEditManuscript: canEditManuscript(state, collection, fragment),
           canViewReviewersDetails: canViewReviewersDetails(state, collection),
           authorCanViewReportsDetails: authorCanViewReportsDetails(
@@ -273,6 +281,10 @@ export default compose(
     toggleReviewerRecommendations: toggle,
     reviewerRecommendationExpanded: expanded,
   })),
+  fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
+    toggleResponseToRevisionRequest: toggle,
+    responseToRevisionRequest: expanded,
+  })),
   fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
     toggleReviewerDetails: toggle,
     reviewerDetailsExpanded: expanded,
@@ -281,11 +293,9 @@ export default compose(
     toggleEditorialComments: toggle,
     editorialCommentsExpanded: expanded,
   })),
-  withProps(({ currentUser, collection, submittedOwnRecommendation }) => ({
+  withProps(({ collection, fragment }) => ({
     getSignedUrl,
-    shouldReview:
-      get(currentUser, 'isReviewer', false) &&
-      isUndefined(submittedOwnRecommendation),
+    isLatestVersion: isLatestVersion(collection, fragment),
   })),
   withInviteHandlingEditor,
   withInviteReviewer,
@@ -298,7 +308,6 @@ export default compose(
         history,
         setError,
         location,
-        shouldReview,
         reviewerReports,
         setEditorInChief,
         clearCustomError,
@@ -306,12 +315,13 @@ export default compose(
         hasManuscriptFailure,
         fetchUpdatedCollection,
         editorialRecommendations,
+        fragment,
         currentUser: {
           isEIC,
           isInvitedHE,
           isInvitedToReview,
           isHEToManuscript,
-          permissions: { canInviteReviewers, canSubmitRevision },
+          permissions: { canInviteReviewers, canSubmitRevision, canReview },
         },
       } = this.props
 
@@ -346,14 +356,14 @@ export default compose(
         this.props.toggleReviewerResponse()
       }
 
-      if (shouldReview) {
+      if (canReview) {
         this.props.toggleReviewerRecommendations()
       }
-
       if (
         isHEToManuscript &&
         !!reviewerReports.length &&
-        editorialRecommendations.length === 0
+        editorialRecommendations.length === 0 &&
+        !fragment.responseToReviewers.content
       ) {
         this.props.toggleReviewerDetails()
       }
@@ -365,6 +375,10 @@ export default compose(
       if (canSubmitRevision) {
         this.props.toggleEditorialComments()
       }
+
+      if (get(fragment, 'responseToReviewers.content', false)) {
+        this.props.toggleResponseToRevisionRequest()
+      }
     },
     componentDidUpdate(prevProps) {
       const {
diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js
index e579d683636db3dfcb7917c961dd8d9f5a02eff8..f98db2189670e9dbb869bdc583cd6636ff3097e3 100644
--- a/packages/component-manuscript/src/components/utils.js
+++ b/packages/component-manuscript/src/components/utils.js
@@ -3,6 +3,7 @@ import {
   has,
   get,
   find,
+  last,
   omit,
   isEmpty,
   debounce,
@@ -74,6 +75,9 @@ export const parseVersion = version => ({
   abstract: get(version, 'metadata.abstract'),
 })
 
+export const isLatestVersion = (collection, fragment) =>
+  get(fragment, 'id', '') === last(get(collection, 'fragments', []))
+
 export const parseJournalIssue = (journal, metadata) =>
   journal.issueTypes.find(t => t.value === get(metadata, 'issue'))
 
diff --git a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
index 756551f82f57ab162c74915c3e47fca32701c4c5..57b8a4297065dd2efe876241e83e886a2b0eebbe 100644
--- a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
+++ b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js
@@ -97,7 +97,7 @@ export default compose(
     },
     deleteResponseFile: ({ setError, changeForm, setFetching }) => file => {
       setFetching(true)
-      return deleteFile(file.id, 'responseToReviewers')
+      return deleteFile({ fileId: file.id }, 'responseToReviewers')
         .then(r => {
           setFetching(false)
           changeForm('revision', 'responseToReviewers.file', null)
diff --git a/packages/component-mts-package/src/PackageManager.js b/packages/component-mts-package/src/PackageManager.js
index b98dbf10308c84b927b10d3f670b285a1b6ca8b7..cb9b8ea4c9fd644ef72c146706dde13348283cc4 100644
--- a/packages/component-mts-package/src/PackageManager.js
+++ b/packages/component-mts-package/src/PackageManager.js
@@ -115,6 +115,26 @@ const uploadFiles = async ({ filename, s3Config, config }) => {
     .catch(fileError(filename))
 }
 
+const deleteFilesS3 = async ({ fileKeys, s3Config }) => {
+  AWS.config.update({
+    secretAccessKey: s3Config.secretAccessKey,
+    accessKeyId: s3Config.accessKeyId,
+    region: s3Config.region,
+  })
+  const s3 = new AWS.S3()
+
+  const params = {
+    Bucket: s3Config.bucket,
+    Delete: {
+      Objects: fileKeys.map(file => ({ Key: file })),
+    },
+  }
+
+  const deleteObjectsS3 = promisify(s3.deleteObjects.bind(s3))
+
+  return deleteObjectsS3(params)
+}
+
 const deleteFile = filename => {
   fs.access(filename, fs.constants.F_OK, err => {
     if (!err) {
@@ -138,4 +158,5 @@ const uploadFTP = ({ filename, config }) => {
 module.exports = {
   createFilesPackage,
   uploadFiles,
+  deleteFilesS3,
 }
diff --git a/packages/components-faraday/src/components/Dashboard/Dashboard.js b/packages/components-faraday/src/components/Dashboard/Dashboard.js
index 0c106443fd6d2da18ebbdce662c5d738bc6b8dd8..a03dce5045de7b34967ca35b9bc7c8d7ec24180c 100644
--- a/packages/components-faraday/src/components/Dashboard/Dashboard.js
+++ b/packages/components-faraday/src/components/Dashboard/Dashboard.js
@@ -4,12 +4,13 @@ import { compose, withProps } from 'recompose'
 import { DashboardItems, DashboardFilters } from './'
 
 const Dashboard = ({
-  deleteProject,
+  journal,
+  isFetching,
   dashboardItems,
+  deleteCollection,
   getFilterOptions,
   changeFilterValue,
   getDefaultFilterValue,
-  journal,
 }) => (
   <Fragment>
     <DashboardFilters
@@ -17,7 +18,11 @@ const Dashboard = ({
       getDefaultFilterValue={getDefaultFilterValue}
       getFilterOptions={getFilterOptions}
     />
-    <DashboardItems deleteProject={deleteProject} list={dashboardItems} />
+    <DashboardItems
+      deleteCollection={deleteCollection}
+      isFetching={isFetching}
+      list={dashboardItems}
+    />
   </Fragment>
 )
 
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardItems.js b/packages/components-faraday/src/components/Dashboard/DashboardItems.js
index f5a5e24df3fff52a255f0a70b427cec11726a782..72d16891c5a40b967a4f7e5491dd9180c05e186d 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardItems.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardItems.js
@@ -5,9 +5,9 @@ import { connect } from 'react-redux'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { withRouter } from 'react-router-dom'
-import { compose, setDisplayName, withHandlers, withProps } from 'recompose'
 import { ManuscriptCard, Row } from 'pubsweet-component-faraday-ui'
 import { canViewReports } from 'pubsweet-component-faraday-selectors'
+import { compose, setDisplayName, withHandlers, withProps } from 'recompose'
 
 const DashboardItem = compose(
   connect((state, { collection }) => ({
@@ -18,7 +18,13 @@ const DashboardItem = compose(
   })),
 )(ManuscriptCard)
 
-const DashboardItems = ({ list, onClick, deleteProject, canViewReports }) => (
+const DashboardItems = ({
+  list,
+  onClick,
+  isFetching,
+  canViewReports,
+  deleteCollection,
+}) => (
   <Root data-test-id="dashboard-list-items">
     {!list.length ? (
       <Row justify="center" mt={4}>
@@ -29,9 +35,10 @@ const DashboardItems = ({ list, onClick, deleteProject, canViewReports }) => (
         <HideLoading key={collection.id}>
           <DashboardItem
             collection={collection}
+            isFetching={isFetching}
             key={collection.id}
             onClick={onClick}
-            onDelete={() => deleteProject(collection)}
+            onDelete={deleteCollection(collection)}
           />
         </HideLoading>
       ))
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
index eda5819b44ca04a7b91afc876a6cec42bba2569c..0cdd9b5ee5b05ba3c0a89a997c1f9fb3fb640344 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
@@ -4,8 +4,9 @@ import { actions } from 'pubsweet-client'
 import { withJournal } from 'xpub-journal'
 import { ConnectPage } from 'xpub-connect'
 import { withRouter } from 'react-router-dom'
-import { compose, withContext } from 'recompose'
 import { selectCurrentUser } from 'xpub-selectors'
+import { compose, withHandlers, withContext } from 'recompose'
+import { handleError, withFetching } from 'pubsweet-component-faraday-ui'
 
 import {
   getUserPermissions,
@@ -32,13 +33,14 @@ export default compose(
         userPermissions,
       }
     },
-    dispatch => ({
-      deleteProject: collection =>
-        dispatch(actions.deleteCollection(collection)),
-    }),
+    {
+      getCollections: actions.getCollections,
+      deleteCollection: actions.deleteCollection,
+    },
   ),
   withRouter,
   withJournal,
+  withFetching,
   withFiltersHOC({
     priority: priorityFilter,
     order: orderFilter,
@@ -50,4 +52,25 @@ export default compose(
     },
     ({ journal, currentUser }) => ({ journal, currentUser }),
   ),
+  withHandlers({
+    deleteCollection: ({
+      setFetching,
+      deleteCollection,
+      getCollections,
+    }) => collection => ({ hideModal, setModalError }) => {
+      setFetching(true)
+      deleteCollection(collection)
+        .then(() => {
+          setFetching(false)
+          hideModal()
+          getCollections()
+        })
+        // again, the error is not being thrown from deleteCollection action and
+        // the catch is never run
+        .catch(err => {
+          setFetching(false)
+          handleError(setModalError)(err)
+        })
+    },
+  }),
 )(Dashboard)
diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js
index c92571ecc8808a78710f8631b5fff43629b0d60b..500a6a103fc300331121a175465c9b18534487d3 100644
--- a/packages/xpub-faraday/config/authsome-helpers.js
+++ b/packages/xpub-faraday/config/authsome-helpers.js
@@ -1,65 +1,11 @@
-const { omit, get, last } = require('lodash')
 const config = require('config')
 const logger = require('@pubsweet/logger')
+const { omit, get, last, chain } = require('lodash')
 
 const statuses = config.get('statuses')
 
-const publicStatusesPermissions = ['author', 'reviewer']
 const authorAllowedStatuses = ['revisionRequested', 'rejected', 'accepted']
 
-const parseAuthorsData = (coll, matchingCollPerm) => {
-  if (['reviewer'].includes(matchingCollPerm.permission)) {
-    coll.authors = coll.authors.map(a => omit(a, ['email']))
-  }
-}
-
-const setPublicStatuses = (coll, matchingCollPerm) => {
-  const status = get(coll, 'status', 'draft')
-  // coll.visibleStatus = statuses[status].public
-  if (publicStatusesPermissions.includes(matchingCollPerm.permission)) {
-    coll.visibleStatus = statuses[status].public
-  }
-}
-
-const filterRefusedInvitations = (coll, user) => {
-  const matchingInv = coll.invitations.find(inv => inv.userId === user.id)
-  if (matchingInv === undefined) return null
-  if (matchingInv.hasAnswer === true && !matchingInv.isAccepted) return null
-  return coll
-}
-
-const filterObjectData = (
-  collectionsPermissions = [],
-  object = {},
-  user = {},
-) => {
-  if (object.type === 'fragment') {
-    const matchingCollPerm = collectionsPermissions.find(
-      collPerm => object.id === collPerm.fragmentId,
-    )
-    if (matchingCollPerm === undefined) return null
-    if (['reviewer'].includes(matchingCollPerm.permission)) {
-      object.files = omit(object.files, ['coverLetter'])
-      if (object.recommendations)
-        object.recommendations = object.recommendations.filter(
-          rec => rec.userId === user.id,
-        )
-    }
-    parseAuthorsData(object, matchingCollPerm)
-    if (['reviewer', 'handlingEditor'].includes(matchingCollPerm.permission)) {
-      return filterRefusedInvitations(object, user)
-    }
-    return object
-  }
-  const matchingCollPerm = collectionsPermissions.find(
-    collPerm => object.id === collPerm.id,
-  )
-  if (matchingCollPerm === undefined) return null
-  setPublicStatuses(object, matchingCollPerm)
-
-  return object
-}
-
 const getTeamsByPermissions = async (
   teamIds = [],
   permissions = [],
@@ -75,12 +21,6 @@ const getTeamsByPermissions = async (
     }),
   )).filter(Boolean)
 
-const heIsInvitedToFragment = async ({ user, Team, collectionId }) =>
-  (await getTeamsByPermissions(user.teams, ['handlingEditor'], Team)).some(
-    // user is a member of the team with access to the fragment's parent collection
-    t => t.members.includes(user.id) && t.object.id === collectionId,
-  )
-
 const getUserPermissions = async ({
   user,
   Team,
@@ -119,12 +59,6 @@ const isHandlingEditor = ({ user, object }) =>
 
 const isInDraft = fragment => !get(fragment, 'submitted')
 
-const hasFragmentInDraft = async ({ object, Fragment }) => {
-  const lastFragmentId = last(get(object, 'fragments'))
-  const fragment = await Fragment.find(lastFragmentId)
-  return isInDraft(fragment)
-}
-
 const filterAuthorRecommendations = (recommendations, status, isLast) => {
   const canViewRecommendations = authorAllowedStatuses.includes(status)
   if (canViewRecommendations || !isLast) {
@@ -236,70 +170,105 @@ const getCollections = async ({ user, models }) => {
       collection.visibleStatus = get(statuses, `${status}.${up.role}.label`)
 
       const role = get(up, 'role', 'author')
-
-      let visibleStatus = get(statuses, `${status}.${role}.label`)
-
-      if (role === 'reviewer' && status !== 'reviewersInvited') {
-        visibleStatus = await updateReviewerVisibleStatusByInvitation({
-          collection,
-          FragmentModel: models.Fragment,
-          user,
-        })
-      }
-
+      const parsedStatuses = await setCollectionStatus({
+        role,
+        user,
+        collection,
+        FragmentModel: models.Fragment,
+      })
       return {
         ...collection,
-        visibleStatus,
+        ...parsedStatuses,
       }
     }),
   )).filter(Boolean)
 }
 
-async function updateReviewerVisibleStatusByInvitation({
+const reviewerActionStatuses = [
+  'underReview',
+  'reviewCompleted',
+  'reviewersInvited',
+]
+const setCollectionStatus = async ({
+  role,
+  user,
   collection,
   FragmentModel,
-  user,
-}) {
-  const fragmentId = last(collection.fragments)
-  const fragment = await FragmentModel.find(fragmentId)
-  const invitation = get(fragment, 'invitations', []).find(
-    inv => inv.userId === user.id,
-  )
-  const recommendationDone =
-    fragment.recommendations &&
-    fragment.recommendations.some(
-      rec =>
-        rec.recommendationType === 'review' &&
-        rec.userId === user.id &&
-        rec.submittedOn,
-    )
+}) => {
+  const status = get(collection, 'status', 'draft')
+
+  if (role !== 'reviewer') {
+    return {
+      status,
+      visibleStatus: get(statuses, `${status}.${role}.label`),
+    }
+  }
+
+  if (reviewerActionStatuses.includes(status)) {
+    const fragmentId = last(collection.fragments)
+    const fragment = await FragmentModel.find(fragmentId)
+
+    const hasPendingInvitation = !chain(fragment)
+      .get('invitations', [])
+      .find(i => i.userId === user.id && !i.hasAnswer)
+      .isUndefined()
+      .value()
+
+    if (hasPendingInvitation) {
+      return {
+        status: 'reviewersInvited',
+        visibleStatus: get(statuses, 'reviewersInvited.reviewer.label'),
+      }
+    }
 
-  if (recommendationDone) {
-    return get(statuses, `${collection.status}.reviewer.label`)
+    const hasSubmittedReport = !chain(fragment)
+      .get('recommendations', [])
+      .find(
+        r =>
+          r.userId === user.id &&
+          r.recommendationType === 'review' &&
+          r.submittedOn,
+      )
+      .isUndefined()
+      .value()
+
+    if (hasSubmittedReport) {
+      return {
+        status: 'reviewCompleted',
+        visibleStatus: get(statuses, 'reviewCompleted.reviewer.label'),
+      }
+    }
+
+    const hasAcceptedInvitation = !chain(fragment)
+      .get('invitations', [])
+      .find(i => i.userId === user.id && i.hasAnswer && i.isAccepted)
+      .isUndefined()
+      .value()
+
+    if (hasAcceptedInvitation) {
+      return {
+        status: 'underReview',
+        visibleStatus: get(statuses, 'underReview.reviewer.label'),
+      }
+    }
   }
 
-  return get(invitation, 'hasAnswer', false) &&
-    get(invitation, 'isAccepted', false)
-    ? get(statuses, `underReview.reviewer.label`)
-    : get(statuses, `reviewersInvited.reviewer.label`)
+  return {
+    status,
+    visibleStatus: get(statuses, `${status}.reviewer.label`),
+  }
 }
 
 module.exports = {
-  filterObjectData,
-  parseAuthorsData,
-  setPublicStatuses,
-  getTeamsByPermissions,
-  filterRefusedInvitations,
   isOwner,
-  isHandlingEditor,
-  getUserPermissions,
-  heIsInvitedToFragment,
-  hasPermissionForObject,
   isInDraft,
-  hasFragmentInDraft,
-  stripeFragmentByRole,
-  getUsersList,
   parseUser,
+  getUsersList,
   getCollections,
-  updateReviewerVisibleStatusByInvitation,
+  isHandlingEditor,
+  getUserPermissions,
+  setCollectionStatus,
+  stripeFragmentByRole,
+  getTeamsByPermissions,
+  hasPermissionForObject,
 }
diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js
index 2bb207ebd4264f3d3210d226bb0134e25e0b1bff..67ab2326468688fca900b38bc23be699e69940d6 100644
--- a/packages/xpub-faraday/config/authsome-mode.js
+++ b/packages/xpub-faraday/config/authsome-mode.js
@@ -67,7 +67,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
     if (get(object, 'type') === 'collection') {
       return {
         filter: async collection => {
-          const status = get(collection, 'status', 'draft')
           const userPermissions = await helpers.getUserPermissions({
             user,
             Team: context.models.Team,
@@ -79,10 +78,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
             )
             .map(up => up.objectId)
 
-          // if (collection.owners.map(o => o.id).includes(user.id)) {
-          //   return collection
-          // }
-          // TODO: check why collPermission can be undefined
           const collPermission = userPermissions.find(
             p =>
               p.objectId === collection.id ||
@@ -90,27 +85,22 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) {
           )
           const role = get(collPermission, 'role', 'author')
 
-          let visibleStatus = get(statuses, `${status}.${role}.label`)
-
-          if (role === 'reviewer' && status !== 'reviewersInvited') {
-            visibleStatus = await helpers.updateReviewerVisibleStatusByInvitation(
-              {
-                collection,
-                FragmentModel: context.models.Fragment,
-                user,
-              },
-            )
-          }
+          const parsedStatuses = await helpers.setCollectionStatus({
+            role,
+            user,
+            collection,
+            FragmentModel: context.models.Fragment,
+          })
 
           return {
             ...collection,
+            ...parsedStatuses,
             fragments:
               role !== 'reviewer'
                 ? collection.fragments
                 : collection.fragments.filter(fragId =>
                     fragmentPermissions.includes(fragId),
                   ),
-            visibleStatus,
           }
         },
       }
diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js
index cc116eecca70a91cb64c085c77fc0c6b6da39cfd..60cd146dec55f085d5535fc0eb934edfcfebc7da 100644
--- a/packages/xpub-faraday/config/validations.js
+++ b/packages/xpub-faraday/config/validations.js
@@ -98,6 +98,7 @@ module.exports = {
             size: Joi.number(),
             url: Joi.string(),
             signedUrl: Joi.string(),
+            submittedOn: Joi.date(),
           }),
         ),
       }),
diff --git a/packages/xpub-faraday/tests/config/authsome-helpers.test.js b/packages/xpub-faraday/tests/config/authsome-helpers.test.js
index 0e51ce6aed419d58cda2bf016f2bbc09d821e8b5..a15e1f9852337441114611dcc2a0e426bf904c5c 100644
--- a/packages/xpub-faraday/tests/config/authsome-helpers.test.js
+++ b/packages/xpub-faraday/tests/config/authsome-helpers.test.js
@@ -195,42 +195,4 @@ describe('Authsome Helpers', () => {
     expect(parsedUser).toHaveProperty('email')
     expect(parsedUser).toHaveProperty('username')
   })
-  describe('updateReviewerVisibleStatusByInvitation', () => {
-    it('should return the fragment status for reviewer when they have done the review', async () => {
-      const { answerReviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: answerReviewer,
-      })
-
-      expect(visibleStatus).toEqual('Review Completed')
-    })
-    it('should return the underReview status for reviewer when they have accepted the review', async () => {
-      const { reviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: reviewer,
-      })
-
-      expect(visibleStatus).toEqual('Complete Review')
-    })
-    it('should return the reviewersInvited status for reviewer when they have to accept the review', async () => {
-      const { recReviewer } = testFixtures.users
-      const { collectionReviewCompleted } = testFixtures.collections
-
-      const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({
-        collection: collectionReviewCompleted,
-        FragmentModel: models.Fragment,
-        user: recReviewer,
-      })
-
-      expect(visibleStatus).toEqual('Respond to Invite')
-    })
-  })
 })