diff --git a/packages/component-manuscript/src/components/ReviewsAndReports.js b/packages/component-manuscript/src/components/ReviewsAndReports.js index 7be2973820b3d11d61f8d5b5d39fef8a05dcaafd..bed0a757d2abb820fdd944e4e5fde7981e0b42c3 100644 --- a/packages/component-manuscript/src/components/ReviewsAndReports.js +++ b/packages/component-manuscript/src/components/ReviewsAndReports.js @@ -34,7 +34,7 @@ const ReviewsAndReports = ({ project, reviewers = [] }) => ( <Root> <Expandable label="Reviewers & Reports" - rightHTML={<ReviewerBreakdown values={project.invitations || []} />} + rightHTML={<ReviewerBreakdown type="reviewer" values={reviewers || []} />} startExpanded > <Tabs activeKey={1} sections={getTabSections(project.id, reviewers)} /> diff --git a/packages/components-faraday/src/components/Reviewers/ReviewerList.js b/packages/components-faraday/src/components/Reviewers/ReviewerList.js index 1e6e44fcdbaaa46724c3c5c8ad2880e89324a870..ec4f3e1d9eb2010de78ed57984bfb14c8500cdcd 100644 --- a/packages/components-faraday/src/components/Reviewers/ReviewerList.js +++ b/packages/components-faraday/src/components/Reviewers/ReviewerList.js @@ -47,8 +47,12 @@ const ReviewersList = ({ <ReviewerEmail>{r.email}</ReviewerEmail> </Column> <Column> - <StatusText>{r.status}</StatusText> - <DateText>{renderTimestamp(r.timestamp)}</DateText> + <StatusText> + {r.status === 'accepted' ? 'Agreed' : r.status} + </StatusText> + <DateText> + {r.respondedOn ? renderTimestamp(r.respondedOn) : ''} + </DateText> </Column> {r.status === 'pending' ? ( <ResendRevoke diff --git a/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js b/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js index 59c667d2e49bc3960bfb472c45b52f10823e0276..36be6c4532cc966add2ec62226b4458d26daf45e 100644 --- a/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js +++ b/packages/components-faraday/src/components/Reviewers/ReviewersDetailsList.js @@ -15,6 +15,7 @@ import { inviteReviewer, selectFetchingInvite, selectReviewersError, + getCollectionReviewers, } from '../../redux/reviewers' const ResendRevoke = withTheme( @@ -32,6 +33,40 @@ const ResendRevoke = withTheme( ), ) +const TR = ({ + reviewer: r, + renderAcceptedLabel, + index, + renderTimestamp, + showConfirmResend, + showConfirmRevoke, +}) => ( + <Row> + <td> + <ReviewerName>{r.name}</ReviewerName>{' '} + {r.status === 'accepted' && ( + <AcceptedReviewer>{renderAcceptedLabel(index)}</AcceptedReviewer> + )} + </td> + <td>{r.invitedOn ? renderTimestamp(r.invitedOn) : ''}</td> + <td> + <StatusText>{r.status === 'accepted' ? 'Agreed' : r.status}</StatusText> + <DateText> + {r.respondedOn ? `: ${renderTimestamp(r.respondedOn)}` : ''} + </DateText> + </td> + <td> {r.submittedOn ? `: ${renderTimestamp(r.submittedOn)}` : ''} </td> + <td width={100}> + {r.status === 'pending' && ( + <ResendRevoke + showConfirmResend={showConfirmResend(r)} + showConfirmRevoke={showConfirmRevoke(r.invitationId)} + status={r.status} + /> + )} + </td> + </Row> +) const ReviewersDetailsList = ({ renderAcceptedLabel, reviewers, @@ -39,40 +74,36 @@ const ReviewersDetailsList = ({ showConfirmRevoke, renderTimestamp, }) => - reviewers.length > 0 && ( + reviewers.length > 0 ? ( <Root> <ScrollContainer> - {reviewers.map((r, index) => ( - <ReviewerItem key={r.invitationId}> - <Column flex={3}> - <div> - <ReviewerName>{r.name}</ReviewerName> - {r.status === 'accepted' && ( - <AcceptedReviewer> - {renderAcceptedLabel(index)} - </AcceptedReviewer> - )} - </div> - <ReviewerEmail>{r.email}</ReviewerEmail> - </Column> - <Column> - <StatusText>{r.status}</StatusText> - <DateText>{renderTimestamp(r.timestamp)}</DateText> - </Column> - {r.status === 'pending' ? ( - <ResendRevoke - showConfirmResend={showConfirmResend(r)} - showConfirmRevoke={showConfirmRevoke(r.invitationId)} - status={r.status} + <Table> + <thead> + <tr> + <td> Full Name </td> + <td> Invited On</td> + <td> Responded On</td> + <td> Submitted On</td> + <td /> + </tr> + </thead> + <tbody> + {reviewers.map((r, index) => ( + <TR + index={index} + key={r.email} + renderAcceptedLabel={renderAcceptedLabel} + renderTimestamp={renderTimestamp} + reviewer={r} + showConfirmResend={showConfirmResend} + showConfirmRevoke={showConfirmRevoke} /> - ) : ( - <Column /> - )} - </ReviewerItem> - ))} + ))} + </tbody> + </Table> </ScrollContainer> </Root> - ) + ) : null const ModalWrapper = compose( connect(state => ({ @@ -84,7 +115,7 @@ const ModalWrapper = compose( )) export default compose( - connect(null, { inviteReviewer, revokeReviewer }), + connect(null, { inviteReviewer, revokeReviewer, getCollectionReviewers }), withModal2(props => ({ modalComponent: ModalWrapper, })), @@ -113,6 +144,7 @@ export default compose( goBackToReviewers, inviteReviewer, collectionId, + getCollectionReviewers, }) => reviewer => () => { showModal({ title: 'Resend reviewer invite', @@ -121,7 +153,9 @@ export default compose( inviteReviewer( pick(reviewer, ['email', 'firstName', 'lastName', 'affiliation']), collectionId, - ).then(hideModal) + ) + .then(() => getCollectionReviewers(collectionId)) + .then(hideModal) }, onCancel: hideModal, }) @@ -133,12 +167,15 @@ export default compose( goBackToReviewers, revokeReviewer, collectionId, + getCollectionReviewers, }) => invitationId => () => { showModal({ title: 'Unassign Reviewer', confirmText: 'Unassign', onConfirm: () => { - revokeReviewer(invitationId, collectionId).then(hideModal) + revokeReviewer(invitationId, collectionId) + .then(() => getCollectionReviewers(collectionId)) + .then(hideModal) }, onCancel: hideModal, }) @@ -154,7 +191,6 @@ const ReviewerEmail = styled.span` ` const ReviewerName = ReviewerEmail.extend` - font-size: ${th('fontSizeBase')}; text-decoration: underline; ` @@ -169,23 +205,46 @@ const StatusText = ReviewerEmail.extend` const DateText = ReviewerEmail.extend`` -const Column = styled.div` - align-items: flex-start; +const ScrollContainer = styled.div` + align-self: stretch; + flex: 1; + overflow: auto; +` +const Root = styled.div` + align-items: stretch; + align-self: stretch; + background-color: ${th('backgroundColorReverse')}; display: flex; flex-direction: column; - justify-content: center; - flex: ${({ flex }) => flex || 1}; + justify-content: flex-start; + height: 25vh; ` -const ReviewerItem = styled.div` - align-items: center; +const Table = styled.table` + border-spacing: 0; + border-collapse: collapse; + width: 100%; + + & thead tr { + border-bottom: ${th('borderDefault')}; + color: ${th('colorPrimary')}; + font-family: ${th('fontReading')}; + font-size: ${th('fontSizeBaseSmall')}; + font-weight: bold; + height: 40px; + text-align: left; + } +` +const Row = styled.tr` border-bottom: ${th('borderDefault')}; - display: flex; - justify-content: space-between; - padding: ${th('subGridUnit')} calc(${th('subGridUnit')} * 2); + color: ${th('colorPrimary')}; + font-family: ${th('fontReading')}; + font-size: ${th('fontSizeBaseSmall')}; + height: 40px; + text-align: left; &:hover { - background-color: ${th('colorSecondary')}; + background-color: ${th('backgroundColor')}; } ` @@ -200,24 +259,8 @@ const ActionButtons = styled.div` cursor: pointer; } - ${ReviewerItem}:hover & { + ${Row}:hover & { opacity: 1; } ` - -const ScrollContainer = styled.div` - align-self: stretch; - flex: 1; - overflow: auto; -` -const Root = styled.div` - align-items: stretch; - align-self: stretch; - background-color: ${th('backgroundColorReverse')}; - border: ${th('borderDefault')}; - display: flex; - flex-direction: column; - justify-content: flex-start; - height: 25vh; -` // #endregion