diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js
index 6e1c18975f59a435cf3ae86e109456ba78b6ed3b..60c7b7764b90a9b3f2ba33289f098380f69f75e7 100644
--- a/packages/component-faraday-selectors/src/index.js
+++ b/packages/component-faraday-selectors/src/index.js
@@ -1,21 +1,21 @@
-import { get, last } from 'lodash'
+import { get, last, chain } from 'lodash'
 import { selectCurrentUser } from 'xpub-selectors'
 
 export const isHEToManuscript = (state, collectionId) => {
-  const currentUserId = get(state, 'currentUser.user.id')
+  const currentUserId = get(state, 'currentUser.user.id', '')
   const collections = get(state, 'collections', [])
   const collection = collections.find(c => c.id === collectionId) || {}
   return get(collection, 'handlingEditor.id') === currentUserId
 }
 
 const canMakeRecommendationStatuses = [
-  'reviewCompleted',
   'heAssigned',
   'underReview',
+  'reviewCompleted',
 ]
 export const canMakeRecommendation = (state, collection, fragment = {}) => {
-  if (fragment.id !== last(collection.fragments)) return false
-  const isHE = isHEToManuscript(state, collection.id)
+  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)
 }
@@ -52,28 +52,27 @@ export const canInviteReviewers = ({ currentUser: { user } }, project) => {
   return isAccepted && (user.id === heId || isAdmin || isEic)
 }
 
-export const getUserToken = ({ currentUser }) => get(currentUser, 'user.token')
+export const getUserToken = ({ currentUser }) =>
+  get(currentUser, 'user.token', '')
 
 export const getHERecommendation = (state, collectionId, fragmentId) => {
-  const recommendations = get(
-    state,
-    `fragments.${fragmentId}.recommendations`,
-    [],
-  )
-  const collection = get(state, 'collections').find(c => c.id === collectionId)
-  const heId = get(collection, `handlingEditor.id`)
+  const heId = chain(state)
+    .get('collections', [])
+    .find(c => c.id === collectionId)
+    .get('hadlingEditor.id', '')
+    .value()
 
   return (
-    recommendations.find(
-      ({ userId, recommendationType }) =>
-        recommendationType === 'editorRecommendation' && userId === heId,
-    ) || {}
+    chain(state)
+      .get(`fragments.${fragmentId}.recommendations`, [])
+      .find(r => r.rec === 'editorRecommendation' && r.userId === heId)
+      .value() || {}
   )
 }
 
 const canMakeDecisionStatuses = ['submitted', 'pendingApproval']
 export const canMakeDecision = (state, collection, fragment = {}) => {
-  if (fragment.id !== last(collection.fragments)) return false
+  if (fragment.id !== last(get(collection, 'fragments', []))) return false
   const status = get(collection, 'status', 'draft')
 
   const isEIC = currentUserIs(state, 'adminEiC')
@@ -83,7 +82,8 @@ export const canMakeDecision = (state, collection, fragment = {}) => {
 const canEditManuscriptStatuses = ['draft', 'technicalChecks', 'inQA']
 export const canEditManuscript = (state, collection, fragment = {}) => {
   const isAdmin = currentUserIs(state, 'isAdmin')
-  if (!isAdmin || fragment.id !== last(collection.fragments)) return false
+  if (!isAdmin || fragment.id !== last(get(collection, 'fragments', [])))
+    return false
   const status = get(collection, 'status', 'draft')
 
   return canEditManuscriptStatuses.includes(status)
diff --git a/packages/component-faraday-ui/src/PersonInvitation.js b/packages/component-faraday-ui/src/PersonInvitation.js
new file mode 100644
index 0000000000000000000000000000000000000000..1ca824bb1354e7e4d00542cb6320fdac9e4b2d61
--- /dev/null
+++ b/packages/component-faraday-ui/src/PersonInvitation.js
@@ -0,0 +1,77 @@
+import React, { Fragment } from 'react'
+import styled from 'styled-components'
+import { compose, withHandlers, defaultProps, setDisplayName } from 'recompose'
+
+import { Text, OpenModal, IconButton, marginHelper } from './'
+
+const PersonInvitation = ({
+  hasAnswer,
+  person: { name },
+  revokeInvitation,
+  resendInvitation,
+  ...rest
+}) => (
+  <Root {...rest}>
+    <Text>{name}</Text>
+    {!hasAnswer && (
+      <Fragment>
+        <OpenModal
+          onConfirm={resendInvitation}
+          title="Are you sure you want to resend the invitation?"
+        >
+          {showModal => (
+            <IconButton
+              icon="refresh-cw"
+              iconSize={2}
+              ml={2}
+              onClick={showModal}
+              secondary
+            />
+          )}
+        </OpenModal>
+        <OpenModal
+          onConfirm={revokeInvitation}
+          title="Are you sure you want to revoke the invitation?"
+        >
+          {showModal => (
+            <IconButton
+              icon="x-circle"
+              iconSize={2}
+              ml={2}
+              onClick={showModal}
+              secondary
+            />
+          )}
+        </OpenModal>
+      </Fragment>
+    )}
+  </Root>
+)
+
+export default compose(
+  defaultProps({
+    person: {
+      name: 'Unassigned',
+    },
+    onRevoke: id => {},
+    onResend: id => {},
+  }),
+  withHandlers({
+    revokeInvitation: ({ id, onRevoke }) => () => {
+      typeof onRevoke === 'function' && onRevoke(id)
+    },
+    resendInvitation: ({ id, onResend, person: { email } }) => () => {
+      typeof onResend === 'function' && onResend(email)
+    },
+  }),
+  setDisplayName('PersonInvitation'),
+)(PersonInvitation)
+
+// #region styles
+const Root = styled.div`
+  align-items: center;
+  display: flex;
+
+  ${marginHelper};
+`
+// #endregion
diff --git a/packages/component-faraday-ui/src/PersonInvitation.md b/packages/component-faraday-ui/src/PersonInvitation.md
new file mode 100644
index 0000000000000000000000000000000000000000..5aff6480f8795faa10c233948e58a2c53f94ac6e
--- /dev/null
+++ b/packages/component-faraday-ui/src/PersonInvitation.md
@@ -0,0 +1,25 @@
+Shows the invited person and the possibility to cancel or resend the invite.
+
+```js
+const invitation = {
+  id: 'b4305ab6-84e6-48a3-9eb9-fbe0ec80c694',
+  role: 'handlingEditor',
+  type: 'invitation',
+  reason: 'because',
+  userId: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+  hasAnswer: false,
+  invitedOn: 1533713919119,
+  isAccepted: false,
+  respondedOn: 1533714034932,
+  person: {
+    id: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+    name: 'Toto Schilacci',
+  },
+};
+
+<PersonInvitation
+  {...invitation}
+  onResend={id => console.log('resend invitation with id', id)}
+  onRevoke={id => console.log('revoke invitation with id', id)}
+  />
+```
diff --git a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js
index c6a288adb7ba74fb10353db4fcb466c013cef986..4ea572b0b6e24d1d9e153f720137c380236d5394 100644
--- a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js
+++ b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js
@@ -1,8 +1,15 @@
-import React from 'react'
+import React, { Fragment } from 'react'
 import styled from 'styled-components'
 import { th } from '@pubsweet/ui-toolkit'
 import { Button, TextField } from '@pubsweet/ui'
-import { compose, withProps, withHandlers, withStateHandlers } from 'recompose'
+import {
+  compose,
+  withProps,
+  defaultProps,
+  withHandlers,
+  setDisplayName,
+  withStateHandlers,
+} from 'recompose'
 
 import {
   Row,
@@ -32,47 +39,60 @@ const AssignHE = ({
         top={12}
       />
     </TextContainer>
-    <Row alignItems="center" height={4} pl={1}>
-      <Item flex={1}>
-        <Label>Name</Label>
-      </Item>
-      <Item flex={2}>
-        <Label>Email</Label>
-      </Item>
-      <Item flex={1} />
-    </Row>
-    {handlingEditors.map((he, index) => (
-      <CustomRow
-        alignItems="center"
-        height={4}
-        isFirst={index === 0}
-        key={he.id}
-        pl={1}
-      >
-        <Item flex={1}>
-          <Text secondary>{he.name}</Text>
-        </Item>
-        <Item flex={2}>
-          <Text secondary>{he.email}</Text>
-        </Item>
-        <Item flex={1}>
-          <OpenModal
-            onConfirm={inviteHandlingEditor(he)}
-            title="Are you sure you want to invite this HE?"
+    {handlingEditors.length > 0 && (
+      <Fragment>
+        <Row alignItems="center" height={4} pl={1}>
+          <Item flex={1}>
+            <Label>Name</Label>
+          </Item>
+          <Item flex={2}>
+            <Label>Email</Label>
+          </Item>
+          <Item flex={1} />
+        </Row>
+        {handlingEditors.map((he, index) => (
+          <CustomRow
+            alignItems="center"
+            height={4}
+            isFirst={index === 0}
+            key={he.id}
+            pl={1}
           >
-            {showModal => (
-              <CustomButton onClick={showModal} size="small">
-                INVITE
-              </CustomButton>
-            )}
-          </OpenModal>
-        </Item>
-      </CustomRow>
-    ))}
+            <Item flex={1}>
+              <Text secondary>{he.name}</Text>
+            </Item>
+            <Item flex={2}>
+              <Text secondary>{he.email}</Text>
+            </Item>
+            <Item flex={1}>
+              <OpenModal
+                onConfirm={inviteHandlingEditor(he)}
+                title="Are you sure you want to invite this HE?"
+              >
+                {showModal => (
+                  <CustomButton onClick={showModal} size="small">
+                    INVITE
+                  </CustomButton>
+                )}
+              </OpenModal>
+            </Item>
+          </CustomRow>
+        ))}
+      </Fragment>
+    )}
   </Root>
 )
 
 export default compose(
+  defaultProps({
+    inviteHandlingEditor: he => {},
+  }),
+  withProps(({ handlingEditors = [] }) => ({
+    handlingEditors: handlingEditors.map(he => ({
+      ...he,
+      name: `${he.firstName} ${he.lastName}`,
+    })),
+  })),
   withStateHandlers(
     { searchValue: '' },
     {
@@ -90,10 +110,13 @@ export default compose(
     ),
   })),
   withHandlers({
-    inviteHandlingEditor: ({ inviteHandlingEditor }) => he => () => {
-      inviteHandlingEditor(he)
+    inviteHandlingEditor: ({ inviteHandlingEditor }) => ({
+      email = '',
+    }) => () => {
+      inviteHandlingEditor(email)
     },
   }),
+  setDisplayName('AssignHandlingEditor'),
 )(AssignHE)
 
 // #region styles
diff --git a/packages/component-faraday-ui/src/index.js b/packages/component-faraday-ui/src/index.js
index 71413c78b0f10310aa085f19d5f8dabbcd6974f5..fd52de8c237374979db60d347a362abaadaec4dc 100644
--- a/packages/component-faraday-ui/src/index.js
+++ b/packages/component-faraday-ui/src/index.js
@@ -1,3 +1,9 @@
+export * from './styledHelpers'
+
+// modals
+export * from './modals'
+export * from './gridItems'
+
 export { default as ActionLink } from './ActionLink'
 export { default as AuthorWithTooltip } from './AuthorWithTooltip'
 export { default as AppBar } from './AppBar'
@@ -8,6 +14,7 @@ export { default as AuthorTagList } from './AuthorTagList'
 export { default as AutosaveIndicator } from './AutosaveIndicator'
 export { default as ContextualBox } from './ContextualBox'
 export { default as DragHandle } from './DragHandle'
+export { default as DownloadZipFiles } from './DownloadZipFiles'
 export { default as FileItem } from './File'
 export { default as FileSection } from './FileSection'
 export { default as IconButton } from './IconButton'
@@ -16,19 +23,14 @@ export { default as Logo } from './Logo'
 export { default as ManuscriptCard } from './ManuscriptCard'
 export { default as ReviewerBreakdown } from './ReviewerBreakdown'
 export { default as PersonInfo } from './PersonInfo'
+export { default as PersonInvitation } from './PersonInvitation'
 export { default as SortableList } from './SortableList'
 export { default as Tag } from './Tag'
 export { default as Text } from './Text'
 export { default as WizardAuthors } from './WizardAuthors'
 export { default as WizardFiles } from './WizardFiles'
 export { default as PreviewFile } from './PreviewFile'
-export { default as DownloadZipFiles } from './DownloadZipFiles'
 
 // Manuscript Details
 export * from './manuscriptDetails'
-
-export * from './styledHelpers'
-
-// modals
-export * from './modals'
-export * from './gridItems'
+export * from './contextualBoxes'
diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
index 63c356d95c093e71546df8e9a38772491be480eb..005fe0b53b8f3647c62a326dce8b70891777349d 100644
--- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
+++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js
@@ -1,14 +1,27 @@
 import React, { Fragment } from 'react'
-import { get } from 'lodash'
-import { H2, H4, DateParser } from '@pubsweet/ui'
-import { compose, withProps } from 'recompose'
+import { get, chain } from 'lodash'
+import { H2, H4, DateParser, Button } from '@pubsweet/ui'
+import {
+  compose,
+  withProps,
+  defaultProps,
+  withHandlers,
+  setDisplayName,
+} from 'recompose'
 
-import { Tag, Text, Row, AuthorTagList } from 'pubsweet-component-faraday-ui'
+import {
+  Tag,
+  Row,
+  Text,
+  AuthorTagList,
+  PersonInvitation,
+} from 'pubsweet-component-faraday-ui'
 
 const ManuscriptHeader = ({
+  renderHE,
   fragment = {},
-  editorInChief = 'Unassigned',
   manuscriptType = {},
+  editorInChief = 'Unassigned',
   collection: { visibleStatus = 'Draft', handlingEditor, customId },
 }) => {
   const { authors = [], metadata = {}, submitted = null } = fragment
@@ -48,18 +61,80 @@ const ManuscriptHeader = ({
           {editorInChief}
         </Text>
         <H4>Handling editor</H4>
-        <Text ml={1} mr={3}>
-          {get(handlingEditor, 'name', 'Unassigned')}
-        </Text>
+        {renderHE()}
       </Row>
     </Fragment>
   )
 }
 
 export default compose(
-  withProps(({ fragment: { metadata }, journal = {} }) => ({
-    manuscriptType: get(journal, 'manuscriptTypes', []).find(
-      t => t.value === get(metadata, 'type', ''),
-    ),
-  })),
+  defaultProps({
+    inviteHE: () => {},
+    revokeInvitation: () => {},
+    resendInvitation: () => {},
+  }),
+  withProps(
+    ({
+      journal = {},
+      fragment: { metadata },
+      collection: { invitations = [] },
+    }) => ({
+      manuscriptType: get(journal, 'manuscriptTypes', []).find(
+        t => t.value === get(metadata, 'type', ''),
+      ),
+      heInvitation: invitations.find(
+        i => i.role === 'handlingEditor' && i.isAccepted,
+      ),
+      pendingInvitation: invitations.find(
+        i => i.role === 'handlingEditor' && !i.hasAnswer,
+      ),
+    }),
+  ),
+  withHandlers({
+    resendInvitation: ({ resendInvitation }) => id => {
+      resendInvitation(id)
+    },
+    revokeInvitation: ({ revokeInvitation }) => id => {
+      revokeInvitation(id)
+    },
+  }),
+  withHandlers({
+    renderHE: ({
+      inviteHE,
+      revokeHE,
+      heInvitation,
+      resendInvitation,
+      revokeInvitation,
+      pendingInvitation,
+      handlingEditors = [],
+      collection: { handlingEditor, invitations = [] },
+    }) => () => {
+      if (pendingInvitation) {
+        const person = chain(handlingEditors)
+          .filter(he => he.id === pendingInvitation.userId)
+          .map(he => ({ ...he, name: `${he.firstName} ${he.lastName}` }))
+          .first()
+          .value()
+
+        return (
+          <PersonInvitation
+            ml={1}
+            {...pendingInvitation}
+            onResend={resendInvitation}
+            onRevoke={revokeInvitation}
+            person={person}
+          />
+        )
+      }
+      if (heInvitation) {
+        return <Text ml={1}>{handlingEditor.name}</Text>
+      }
+      return (
+        <Button ml={1} onClick={inviteHE} primary size="small">
+          Invite
+        </Button>
+      )
+    },
+  }),
+  setDisplayName('ManuscriptHeader'),
 )(ManuscriptHeader)
diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md
index 7122002cd093fe7e23acaf86db687f94389796e3..5c390e8daef5c5d4d06e37bec7da857cddcce12b 100644
--- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md
+++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md
@@ -1,4 +1,4 @@
-Manuscript header
+Manuscript header without a HE assigned.
 
 ```js
 const authors = [
@@ -39,6 +39,7 @@ const collection = {
     id: 'he-1',
     name: 'Handlington Ignashevici',
   },
+  invitations: [],
 }
 
 const fragment = {
@@ -69,11 +70,213 @@ const journal = {
       abstractRequired: true,
     },
   ],
+};
+
+<ManuscriptHeader
+  collection={collection}
+  fragment={fragment}
+  journal={journal}
+  inviteHE={() => console.log('go to invite HE ctx box')}
+  revokeInvitation={id => console.log('revoke invitation', id)}
+  resendInvitation={id => console.log('resend invitation', id)}
+/>
+```
+
+Manuscript header with a pending HE invitation.
+
+```js
+const authors = [
+  {
+    email: 'john.doe@gmail.com',
+    firstName: 'John',
+    lastName: 'Doe',
+    isSubmitting: true,
+  },
+  {
+    email: 'michael.felps@gmail.com',
+    firstName: 'Michael',
+    lastName: 'Felps',
+    isSubmitting: true,
+    isCorresponding: true,
+  },
+  {
+    email: 'barrack.obama@gmail.com',
+    firstName: 'Barrack',
+    lastName: 'Obama',
+  },
+  {
+    email: 'barrack.obama@gmail1.com',
+    firstName: 'Barrack 1',
+    lastName: 'Obama',
+  },
+  {
+    email: 'barrack.obama@gmail2.com',
+    firstName: 'Barrack 2',
+    lastName: 'Obama',
+  },
+]
+
+const collection = {
+  customId: '55113358',
+  visibleStatus: 'Pending Approval',
+  handlingEditor: {
+    id: 'he-1',
+    name: 'Handlington Ignashevici',
+  },
+  invitations: [
+    {
+      id: 'b4305ab6-84e6-48a3-9eb9-fbe0ec80c694',
+      role: 'handlingEditor',
+      type: 'invitation',
+      reason: 'because',
+      userId: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+      hasAnswer: false,
+      invitedOn: 1533713919119,
+      isAccepted: false,
+      person: {
+        id: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+        name: 'Toto Schilacci',
+      },
+    },
+  ],
+}
+
+const fragment = {
+  authors,
+  created: Date.now(),
+  submitted: Date.now(),
+  metadata: {
+    journal: 'Awesomeness',
+    title: 'A very ok title with many authors',
+    type: 'research',
+  },
 }
 
-;<ManuscriptHeader
+const journal = {
+  manuscriptTypes: [
+    {
+      label: 'Research',
+      value: 'research',
+      author: true,
+      peerReview: true,
+      abstractRequired: true,
+    },
+    {
+      label: 'Review',
+      value: 'review',
+      author: true,
+      peerReview: true,
+      abstractRequired: true,
+    },
+  ],
+};
+
+<ManuscriptHeader
+  collection={collection}
+  fragment={fragment}
+  journal={journal}
+  inviteHE={() => console.log('go to invite HE ctx box')}
+  revokeInvitation={id => console.log('revoke invitation', id)}
+  resendInvitation={id => console.log('resend invitation', id)}
+/>
+```
+
+Manuscript header with a pending HE invitation.
+
+```js
+const authors = [
+  {
+    email: 'john.doe@gmail.com',
+    firstName: 'John',
+    lastName: 'Doe',
+    isSubmitting: true,
+  },
+  {
+    email: 'michael.felps@gmail.com',
+    firstName: 'Michael',
+    lastName: 'Felps',
+    isSubmitting: true,
+    isCorresponding: true,
+  },
+  {
+    email: 'barrack.obama@gmail.com',
+    firstName: 'Barrack',
+    lastName: 'Obama',
+  },
+  {
+    email: 'barrack.obama@gmail1.com',
+    firstName: 'Barrack 1',
+    lastName: 'Obama',
+  },
+  {
+    email: 'barrack.obama@gmail2.com',
+    firstName: 'Barrack 2',
+    lastName: 'Obama',
+  },
+]
+
+const collection = {
+  customId: '55113358',
+  visibleStatus: 'Pending Approval',
+  handlingEditor: {
+    id: 'he-1',
+    name: 'Handlington Ignashevici',
+  },
+  invitations: [
+    {
+      id: 'b4305ab6-84e6-48a3-9eb9-fbe0ec80c694',
+      role: 'handlingEditor',
+      type: 'invitation',
+      reason: 'because',
+      userId: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+      hasAnswer: true,
+      invitedOn: 1533713919119,
+      isAccepted: true,
+      respondedOn: 1533714034932,
+      person: {
+        id: 'cb7e3e26-6a09-4b79-a6ff-4d1235ee2381',
+        name: 'Toto Schilacci',
+      },
+    },
+  ],
+}
+
+const fragment = {
+  authors,
+  created: Date.now(),
+  submitted: Date.now(),
+  metadata: {
+    journal: 'Awesomeness',
+    title: 'A very ok title with many authors',
+    type: 'research',
+  },
+}
+
+const journal = {
+  manuscriptTypes: [
+    {
+      label: 'Research',
+      value: 'research',
+      author: true,
+      peerReview: true,
+      abstractRequired: true,
+    },
+    {
+      label: 'Review',
+      value: 'review',
+      author: true,
+      peerReview: true,
+      abstractRequired: true,
+    },
+  ],
+};
+
+<ManuscriptHeader
   collection={collection}
   fragment={fragment}
   journal={journal}
+  inviteHE={() => console.log('go to invite HE ctx box')}
+  revokeInvitation={id => console.log('revoke invitation', id)}
+  resendInvitation={id => console.log('resend invitation', id)}
 />
 ```
diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js
index aeca22f0ab50d97a744212cd7a164c07ee16d808..ff0e5b1301733c08d1735aa7b198502739623781 100644
--- a/packages/component-manuscript/src/components/ManuscriptLayout.js
+++ b/packages/component-manuscript/src/components/ManuscriptLayout.js
@@ -4,16 +4,21 @@ import styled from 'styled-components'
 import {
   Text,
   ManuscriptHeader,
-  ManuscriptDetailsTop,
   ManuscriptMetadata,
+  ManuscriptDetailsTop,
+  ContextualBox,
+  AssignHE,
 } from 'pubsweet-component-faraday-ui'
 
 const ManuscriptLayout = ({
   history,
-  getSignedUrl,
+  assignHE,
+  revokeHE,
   currentUser,
+  getSignedUrl,
   editorInChief,
   canMakeRevision,
+  handlingEditors,
   hasResponseToReviewers,
   editorialRecommendations,
   journal = {},
@@ -36,13 +41,24 @@ const ManuscriptLayout = ({
           collection={collection}
           editorInChief={editorInChief}
           fragment={fragment}
+          handlingEditors={handlingEditors}
           journal={journal}
+          resendInvitation={assignHE}
+          revokeInvitation={revokeHE}
         />
         <ManuscriptMetadata
           currentUser={currentUser}
           fragment={fragment}
           getSignedUrl={getSignedUrl}
         />
+        {currentUser.canAssignHE && (
+          <ContextualBox label="Assign Handling Editor">
+            <AssignHE
+              handlingEditors={handlingEditors}
+              inviteHandlingEditor={assignHE}
+            />
+          </ContextualBox>
+        )}
       </Fragment>
     ) : (
       <Text>Loading...</Text>
diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js
index 88f14ae12f0b56c6cf00ef861628351e56b5f41e..cdda8c169507720aa7d44b0f309ccefa0d3a4629 100644
--- a/packages/component-manuscript/src/components/ManuscriptPage.js
+++ b/packages/component-manuscript/src/components/ManuscriptPage.js
@@ -26,12 +26,9 @@ import {
   clearCustomError,
 } from 'pubsweet-components-faraday/src/redux/errors'
 import { selectEditorialRecommendations } from 'pubsweet-components-faraday/src/redux/recommendations'
-import {
-  getHandlingEditors,
-  selectHandlingEditors,
-} from 'pubsweet-components-faraday/src/redux/editors'
 import {
   getUserToken,
+  currentUserIs,
   canMakeRevision,
   canMakeDecision,
   canEditManuscript,
@@ -42,6 +39,13 @@ import {
 
 import ManuscriptLayout from './ManuscriptLayout'
 import { parseSearchParams, redirectToError } from './utils'
+import {
+  canAssignHE,
+  getHandlingEditors,
+  assignHandlingEditor,
+  revokeHandlingEditor,
+  selectHandlingEditors,
+} from '../redux/editors'
 
 export default compose(
   setDisplayName('ManuscriptPage'),
@@ -69,16 +73,20 @@ export default compose(
       getSignedUrl,
       clearCustomError,
       reviewerDecision,
+      assignHandlingEditor,
+      revokeHandlingEditor,
       getFragment: actions.getFragment,
       getCollection: actions.getCollection,
       updateVersion: actions.updateFragment,
     },
   ),
-  connect((state, { currentUser, collection, fragment }) => ({
+  connect((state, { currentUser, match, collection, fragment }) => ({
     currentUser: {
       ...currentUser,
       token: getUserToken(state),
+      isEIC: currentUserIs(state, 'adminEiC'),
       isReviewer: currentUserIsReviewer(state),
+      canAssignHE: canAssignHE(state, match.params.project),
     },
     canMakeRevision: canMakeRevision(state, collection, fragment),
     permissions: {
@@ -89,12 +97,7 @@ export default compose(
     },
   })),
   ConnectPage(({ currentUser, handlingEditors, collection }) => {
-    const he = get(collection, 'handlingEditor')
-    if (
-      !he &&
-      !handlingEditors.length &&
-      (get(currentUser, 'admin') || get(currentUser, 'editorInChief'))
-    ) {
+    if (currentUser.isEIC) {
       return [getHandlingEditors()]
     }
     return []
@@ -111,6 +114,34 @@ export default compose(
         setEiC(`${firstName} ${lastName}`)
       }
     },
+    assignHE: ({
+      fragment,
+      collection,
+      getFragment,
+      getCollection,
+      assignHandlingEditor,
+      collection: { id: collectionId },
+    }) => email => {
+      assignHandlingEditor({
+        email,
+        collectionId,
+      }).then(() => {
+        getCollection({ id: collectionId })
+        getFragment(collection, fragment)
+      })
+    },
+    revokeHE: ({
+      getCollection,
+      revokeHandlingEditor,
+      collection: { id: collectionId },
+    }) => invitationId => {
+      revokeHandlingEditor({
+        invitationId,
+        collectionId,
+      }).then(() => {
+        getCollection({ id: collectionId })
+      })
+    },
   }),
   lifecycle({
     componentDidMount() {
diff --git a/packages/component-manuscript/src/index.js b/packages/component-manuscript/src/index.js
index 8d52f148e8c8927db1d86494ca404451da5a917d..01aa93785c2d01ec0fb22a177c2c6a123b2e71b0 100644
--- a/packages/component-manuscript/src/index.js
+++ b/packages/component-manuscript/src/index.js
@@ -1,5 +1,8 @@
 module.exports = {
   client: {
     components: [() => require('./components')],
+    reducers: {
+      editors: () => require('./redux/editors').default,
+    },
   },
 }
diff --git a/packages/components-faraday/src/redux/editors.js b/packages/component-manuscript/src/redux/editors.js
similarity index 78%
rename from packages/components-faraday/src/redux/editors.js
rename to packages/component-manuscript/src/redux/editors.js
index 17984b255e19f6a3e51ac84481487980774744c1..933b4b23f6f0b54f0f1ea95ebad6ab763870c584 100644
--- a/packages/components-faraday/src/redux/editors.js
+++ b/packages/component-manuscript/src/redux/editors.js
@@ -1,13 +1,14 @@
-import { get } from 'lodash'
+import { get, chain } from 'lodash'
 import {
-  get as apiGet,
   create,
   remove,
   update,
+  get as apiGet,
 } from 'pubsweet-client/src/helpers/api'
+import { currentUserIs } from 'pubsweet-component-faraday-selectors'
 
-const EDITORS_REQUEST = 'EDITORS_REQUEST'
 const EDITORS_DONE = 'EDITORS_DONE'
+const EDITORS_REQUEST = 'EDITORS_REQUEST'
 const SET_HANDLING_EDITORS = 'SET_HANDLING_EDITORS'
 
 const setHandlingEditors = editors => ({
@@ -15,8 +16,19 @@ const setHandlingEditors = editors => ({
   payload: { editors },
 })
 
-export const selectFetching = state => get(state, 'editors.isFetching')
-export const selectHandlingEditors = state => get(state, 'editors.editors')
+export const selectFetching = state => get(state, 'editors.isFetching', false)
+export const selectHandlingEditors = state => get(state, 'editors.editors', [])
+
+export const canAssignHE = (state, collectionId) => {
+  const isEIC = currentUserIs(state, 'adminEiC')
+  const hasHE = chain(state)
+    .get('collections', [])
+    .find(c => c.id === collectionId)
+    .get('handlingEditor')
+    .value()
+
+  return isEIC && !hasHE
+}
 
 const editorsRequest = () => ({ type: EDITORS_REQUEST })
 const editorsDone = () => ({ type: EDITORS_DONE })
@@ -26,7 +38,7 @@ export const getHandlingEditors = () => dispatch =>
     dispatch(setHandlingEditors(res.users)),
   )
 
-export const assignHandlingEditor = (email, collectionId) => dispatch => {
+export const assignHandlingEditor = ({ email, collectionId }) => dispatch => {
   dispatch(editorsRequest())
   return create(`/collections/${collectionId}/invitations`, {
     email,
@@ -43,10 +55,10 @@ export const assignHandlingEditor = (email, collectionId) => dispatch => {
   )
 }
 
-export const revokeHandlingEditor = (
+export const revokeHandlingEditor = ({
   invitationId,
   collectionId,
-) => dispatch => {
+}) => dispatch => {
   dispatch(editorsRequest())
   return remove(
     `/collections/${collectionId}/invitations/${invitationId}`,
diff --git a/packages/component-manuscript/src/redux/index.js b/packages/component-manuscript/src/redux/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..05f36f6d43441bbc101f5490a0aa3677ecf26a15
--- /dev/null
+++ b/packages/component-manuscript/src/redux/index.js
@@ -0,0 +1 @@
+export { default as editors } from './editors'
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
index 1e9e2825c054b65a057e624b72cc6e839fb8e5d4..ee51f5000102853721063b5c7666f4e7db5365ac 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js
@@ -1,4 +1,3 @@
-import { get } from 'lodash'
 import PropTypes from 'prop-types'
 import { connect } from 'react-redux'
 import { actions } from 'pubsweet-client'
@@ -15,7 +14,6 @@ import {
 } from 'pubsweet-component-faraday-selectors'
 
 import { Dashboard } from './'
-import { getHandlingEditors } from '../../redux/editors'
 import { priorityFilter, orderFilter, withFiltersHOC } from '../Filters'
 
 export default compose(
@@ -59,12 +57,6 @@ export default compose(
       createDraftSubmission: () => dispatch(createDraftSubmission(history)),
     }),
   ),
-  ConnectPage(
-    ({ currentUser }) =>
-      get(currentUser, 'admin') || get(currentUser, 'editorInChief')
-        ? [getHandlingEditors()]
-        : [],
-  ),
   withRouter,
   withJournal,
   withFiltersHOC({
diff --git a/packages/components-faraday/src/index.js b/packages/components-faraday/src/index.js
index be69a5315674890955a7de5fa07fcbfdd22bf9a5..db4b6cd565c1db6e4afba19f44272d8200786c50 100644
--- a/packages/components-faraday/src/index.js
+++ b/packages/components-faraday/src/index.js
@@ -4,7 +4,6 @@ module.exports = {
     reducers: {
       authors: () => require('./redux/authors').default,
       customError: () => require('./redux/errors').default,
-      editors: () => require('./redux/editors').default,
       files: () => require('./redux/files').default,
       reviewers: () => require('./redux/reviewers').default,
       technicalCheck: () => require('./redux/technicalCheck').default,
diff --git a/packages/components-faraday/src/redux/index.js b/packages/components-faraday/src/redux/index.js
index c7fd43a9557173a35047de82ce6f5e64f18a8e03..30c41635ad5620a20b3ab66da9d7e4f8e34dc8df 100644
--- a/packages/components-faraday/src/redux/index.js
+++ b/packages/components-faraday/src/redux/index.js
@@ -1,7 +1,6 @@
 export { default as files } from './files'
 export { default as errors } from './errors'
 export { default as authors } from './authors'
-export { default as editors } from './editors'
 export { default as reviewers } from './reviewers'
 export { default as technicalCheck } from './technicalCheck'
 export { default as recommendations } from './recommendations'
diff --git a/packages/hindawi-theme/src/elements/Button.js b/packages/hindawi-theme/src/elements/Button.js
index 34720cd8f3d58e012918c38dd57736cb8e676030..e6f844be07b67b06e48fdbbacbf85942fc5ef2d6 100644
--- a/packages/hindawi-theme/src/elements/Button.js
+++ b/packages/hindawi-theme/src/elements/Button.js
@@ -12,9 +12,11 @@ const primary = css`
     background-color: ${lighten('button.primary', 0.1)};
   }
 
+  &:focus,
   &:active {
     background-color: ${th('button.primary')};
     border-color: ${th('button.borderActive')};
+    outline: none;
   }
 
   &[disabled] {