From b209b804e7e5e5d3d773b788a628d80dfdfb5f93 Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Wed, 17 Feb 2021 13:37:19 -0600 Subject: [PATCH 1/6] Reports that are submitted or approved cannot be updated --- frontend/src/components/Navigator/index.js | 15 ++- frontend/src/fetchers/activityReports.js | 6 + .../Pages/Review/Approver/index.js | 80 ++++++++--- .../Pages/Review/Submitter/NeedsAction.js | 15 +-- .../Pages/Review/Submitter/Submitted.js | 50 +++++++ .../Pages/Review/Submitter/index.js | 127 +++++++++++++----- .../Pages/Review/__tests__/index.js | 7 - .../ActivityReport/Pages/Review/index.js | 44 +++--- .../src/pages/ActivityReport/Pages/index.js | 2 + .../pages/ActivityReport/__tests__/index.js | 2 + frontend/src/pages/ActivityReport/index.js | 46 ++++--- src/policies/activityReport.js | 14 +- src/policies/activityReport.test.js | 18 +++ src/routes/activityReports/handlers.js | 22 ++- src/routes/activityReports/index.js | 2 + src/services/activityReports.js | 13 ++ 16 files changed, 355 insertions(+), 108 deletions(-) create mode 100644 frontend/src/pages/ActivityReport/Pages/Review/Submitter/Submitted.js diff --git a/frontend/src/components/Navigator/index.js b/frontend/src/components/Navigator/index.js index 494cd9afbc..77687d45b7 100644 --- a/frontend/src/components/Navigator/index.js +++ b/frontend/src/components/Navigator/index.js @@ -22,12 +22,14 @@ import SideNav from './components/SideNav'; import NavigatorHeader from './components/NavigatorHeader'; function Navigator({ + editable, formData, updateFormData, initialLastUpdated, pages, onFormSubmit, onReview, + onResetToDraft, currentPage, additionalData, onSave, @@ -71,6 +73,9 @@ function Navigator({ }; const onSaveForm = async (completed, index) => { + if (!editable) { + return; + } const data = { ...formData, ...getValues(), pageState: newNavigatorState(completed) }; const newIndex = index === page.position ? null : index; try { @@ -103,7 +108,12 @@ function Navigator({ const navigatorPages = pages.map((p) => { const current = p.position === page.position; - const stateOfPage = current ? IN_PROGRESS : pageState[p.position]; + + let stateOfPage = pageState[p.position]; + if (stateOfPage !== COMPLETE) { + stateOfPage = current ? IN_PROGRESS : pageState[p.position]; + } + const state = p.review ? formData.status : stateOfPage; return { label: p.label, @@ -135,6 +145,7 @@ function Navigator({ additionalData, onReview, approvingManager, + onResetToDraft, )} {!page.review && ( @@ -159,6 +170,8 @@ function Navigator({ } Navigator.propTypes = { + onResetToDraft: PropTypes.func.isRequired, + editable: PropTypes.bool.isRequired, formData: PropTypes.shape({ status: PropTypes.string, pageState: PropTypes.shape({}), diff --git a/frontend/src/fetchers/activityReports.js b/frontend/src/fetchers/activityReports.js index 429f4dee9c..c74888c845 100644 --- a/frontend/src/fetchers/activityReports.js +++ b/frontend/src/fetchers/activityReports.js @@ -58,3 +58,9 @@ export const reviewReport = async (reportId, data) => { const report = await put(url, data); return report.json(); }; + +export const resetToDraft = async (reportId) => { + const url = join(activityReportUrl, reportId.toString(DECIMAL_BASE), 'reset'); + const response = await put(url); + return response.json(); +}; diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js index aee8a7e675..71d8b84a3e 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js @@ -1,9 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Alert } from '@trussworks/react-uswds'; import Review from './Review'; import Approved from './Approved'; import { REPORT_STATUSES } from '../../../../../Constants'; +import Container from '../../../../../components/Container'; const Approver = ({ register, @@ -12,31 +14,66 @@ const Approver = ({ reviewed, formData, valid, + children, + error, }) => { const { managerNotes, additionalNotes, status } = formData; const review = status === REPORT_STATUSES.SUBMITTED || status === REPORT_STATUSES.NEEDS_ACTION; const approved = status === REPORT_STATUSES.APPROVED; + const { author } = formData; - return ( - <> - {review - && ( - + const renderTopAlert = () => ( + + {review && ( + <> + + { author.name } + {' '} + has requested approval for this activity report. + +
+ Please review all information in each section before submitting for approval. + )} - {approved - && ( - + {approved && ( + <> + This report has been approved and is no longer editable + )} +
+ ); + + return ( + <> + {renderTopAlert()} + {children} + + {error && ( + + Error +
+ {error} +
+ )} + {review + && ( + + )} + {approved + && ( + + )} +
); }; @@ -47,6 +84,8 @@ Approver.propTypes = { onFormReview: PropTypes.func.isRequired, reviewed: PropTypes.bool.isRequired, valid: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + error: PropTypes.string, formData: PropTypes.shape({ approvingManager: PropTypes.shape({ name: PropTypes.string, @@ -54,7 +93,12 @@ Approver.propTypes = { managerNotes: PropTypes.string, additionalNotes: PropTypes.string, status: PropTypes.string, + author: PropTypes.string, }).isRequired, }; +Approver.defaultProps = { + error: '', +}; + export default Approver; diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/NeedsAction.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/NeedsAction.js index e7da7eeb78..80b7985209 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/NeedsAction.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/NeedsAction.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Alert, Button } from '@trussworks/react-uswds'; +import { Button } from '@trussworks/react-uswds'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; @@ -17,15 +17,6 @@ const NeedsAction = ({ return ( <> - - - { approvingManager.name } - {' '} - has requested updates to this activity report - -
- Please review the manager notes below and re-submit for approval. -

Review and re-submit report

@@ -40,7 +31,7 @@ const NeedsAction = ({ Manager notes

- { managerNotes } + { managerNotes || 'No manager notes' }

@@ -53,7 +44,7 @@ const NeedsAction = ({ {' '} from {' '} - { approvingManager.name || 'No manager notes' } + { approvingManager.name }
diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Submitted.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Submitted.js new file mode 100644 index 0000000000..0f39821bc7 --- /dev/null +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Submitted.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { + Alert, Button, +} from '@trussworks/react-uswds'; + +const Submitted = ({ + additionalNotes, + approvingManager, + resetToDraft, +}) => ( + <> + + Success +
+ This report was successfully submitted for approval +
+
+

+ Creator notes +
+
+ { additionalNotes || 'No creator notes' } +

+
+

+ {approvingManager.name} + {' '} + is the approving manager for this report. + {' '} +

+ + +); + +Submitted.propTypes = { + additionalNotes: PropTypes.string, + approvingManager: PropTypes.shape({ + id: PropTypes.number, + name: PropTypes.string, + }).isRequired, + resetToDraft: PropTypes.func.isRequired, +}; + +Submitted.defaultProps = { + additionalNotes: '', +}; + +export default Submitted; diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js index a29fa07c3c..2a9815d8bf 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js @@ -1,14 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { Alert } from '@trussworks/react-uswds'; +import Container from '../../../../../components/Container'; +import { REPORT_STATUSES } from '../../../../../Constants'; import DraftReview from './Draft'; import NeedsAction from './NeedsAction'; import Approved from './Approved'; - -import { REPORT_STATUSES } from '../../../../../Constants'; +import Submitted from './Submitted'; const Submitter = ({ - submitted, allComplete, register, approvers, @@ -16,6 +17,9 @@ const Submitter = ({ handleSubmit, onFormSubmit, formData, + onResetToDraft, + children, + error, }) => { const { approvingManager, @@ -23,47 +27,102 @@ const Submitter = ({ additionalNotes, status, } = formData; - const notReviewed = status === REPORT_STATUSES.DRAFT || status === REPORT_STATUSES.SUBMITTED; + const draft = status === REPORT_STATUSES.DRAFT; + const submitted = status === REPORT_STATUSES.SUBMITTED; const needsAction = status === REPORT_STATUSES.NEEDS_ACTION; const approved = status === REPORT_STATUSES.APPROVED; - return ( + const resetToDraft = async () => { + await onResetToDraft(); + }; + + const renderTopAlert = () => ( <> - {notReviewed - && ( - + {needsAction && ( + + + { approvingManager.name } + {' '} + has requested updates to this activity report. + +
+ Please review the manager notes below and re-submit for approval. +
)} - {needsAction - && ( - + {approved && ( + + This report has been approved and is no longer editable + )} - {approved - && ( - + {submitted && ( + + Report is not editable +
+ This report is no longer editable while it is waiting for manager approval. + If you wish to update this report click "Reset to Draft" below to + move the report back to draft mode. +
)} ); + + return ( + <> + {renderTopAlert()} + {children} + + {error && ( + + Error +
+ {error} +
+ )} + {draft + && ( + + )} + {submitted + && ( + + )} + {needsAction + && ( + + )} + {approved + && ( + + )} +
+ + ); }; Submitter.propTypes = { - submitted: PropTypes.bool.isRequired, + onResetToDraft: PropTypes.func.isRequired, + error: PropTypes.string, + children: PropTypes.node.isRequired, allComplete: PropTypes.bool.isRequired, register: PropTypes.func.isRequired, approvers: PropTypes.arrayOf(PropTypes.shape({ @@ -83,4 +142,8 @@ Submitter.propTypes = { }).isRequired, }; +Submitter.defaultProps = { + error: '', +}; + export default Submitter; diff --git a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js index 6ca86152d6..96330aa66c 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js @@ -148,13 +148,6 @@ describe('ReviewSubmit', () => { }); }); - it('a success modal is shown once submitted', async () => { - renderReview(true, false, REPORT_STATUSES.DRAFT, {}, () => {}, () => {}, 1); - userEvent.click(await screen.findByTestId('button')); - const alert = await screen.findByTestId('alert'); - expect(alert).toHaveClass('usa-alert--success'); - }); - it('initializes the form with "initialData"', async () => { renderReview(true, false, REPORT_STATUSES.DRAFT, { additionalNotes: 'test' }); const textBox = await screen.findByLabelText('Creator notes'); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/index.js b/frontend/src/pages/ActivityReport/Pages/Review/index.js index 33e76ef245..e6e75d1af6 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/index.js @@ -1,16 +1,14 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { - Alert, Accordion, + Accordion, } from '@trussworks/react-uswds'; import { Helmet } from 'react-helmet'; import { useFormContext } from 'react-hook-form'; -import Container from '../../../../components/Container'; import Submitter from './Submitter'; import Approver from './Approver'; import './index.css'; -import { REPORT_STATUSES } from '../../../../Constants'; const ReviewSubmit = ({ allComplete, @@ -20,23 +18,21 @@ const ReviewSubmit = ({ approvers, approvingManager, formData, + onResetToDraft, }) => { const { handleSubmit, register, formState } = useFormContext(); const { additionalNotes, status } = formData; const { isValid } = formState; const valid = allComplete && isValid; - const [submitted, updateSubmitted] = useState(status === REPORT_STATUSES.SUBMITTED); const [reviewed, updateReviewed] = useState(false); const [error, updateError] = useState(); const onFormSubmit = async (data) => { try { await onSubmit(data); - updateSubmitted(true); updateError(); } catch (e) { - updateSubmitted(false); updateError('Unable to submit report'); } }; @@ -52,35 +48,38 @@ const ReviewSubmit = ({ } }; + const onReset = async () => { + try { + await onResetToDraft(); + updateError(); + } catch (e) { + updateError('Unable to reset Activity Report to draft'); + } + }; + return ( <> Review and submit - - - {error && ( - - Error -
- {error} -
- )} - {!approvingManager + {!approvingManager && ( + error={error} + > + + )} - {approvingManager + {approvingManager && ( + > + + )} -
); }; @@ -108,6 +109,7 @@ ReviewSubmit.propTypes = { allComplete: PropTypes.bool.isRequired, onSubmit: PropTypes.func.isRequired, onReview: PropTypes.func.isRequired, + onResetToDraft: PropTypes.func.isRequired, approvingManager: PropTypes.bool.isRequired, formData: PropTypes.shape({ additionalNotes: PropTypes.string, diff --git a/frontend/src/pages/ActivityReport/Pages/index.js b/frontend/src/pages/ActivityReport/Pages/index.js index c8f9071c37..80dc8d6728 100644 --- a/frontend/src/pages/ActivityReport/Pages/index.js +++ b/frontend/src/pages/ActivityReport/Pages/index.js @@ -34,6 +34,7 @@ const reviewPage = { additionalData, onReview, approvingManager, + onResetToDraft, ) => ( reviewItem(p.path, p.label, p.sections, formData)) } diff --git a/frontend/src/pages/ActivityReport/__tests__/index.js b/frontend/src/pages/ActivityReport/__tests__/index.js index b12e811eef..28533a7a94 100644 --- a/frontend/src/pages/ActivityReport/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/__tests__/index.js @@ -12,6 +12,7 @@ import userEvent from '@testing-library/user-event'; import { withText } from '../../../testHelpers'; import ActivityReport from '../index'; +import { REPORT_STATUSES } from '../../../Constants'; const formData = () => ({ deliveryMethod: 'in-person', @@ -31,6 +32,7 @@ const formData = () => ({ participants: ['CEO / CFO / Executive'], programTypes: ['type 1'], requester: 'grantee', + status: REPORT_STATUSES.DRAFT, resourcesUsed: 'eclkcurl', startDate: moment().format('MM/DD/YYYY'), targetPopulations: ['target 1'], diff --git a/frontend/src/pages/ActivityReport/index.js b/frontend/src/pages/ActivityReport/index.js index d784d4c33d..50e9099ca1 100644 --- a/frontend/src/pages/ActivityReport/index.js +++ b/frontend/src/pages/ActivityReport/index.js @@ -26,6 +26,7 @@ import { getCollaborators, getApprovers, reviewReport, + resetToDraft, } from '../../fetchers/activityReports'; // All new reports will show these two goals @@ -76,7 +77,7 @@ function ActivityReport({ match, user, location }) { const [formData, updateFormData] = useState(); const [initialAdditionalData, updateAdditionalData] = useState({}); const [approvingManager, updateApprovingManager] = useState(false); - const [canWrite, updateCanWrite] = useState(false); + const [editable, updateEditable] = useState(false); const [initialLastUpdated, updateInitialLastUpdated] = useState(); const reportId = useRef(); @@ -114,12 +115,14 @@ function ActivityReport({ match, user, location }) { const isCollaborator = report.collaborators && report.collaborators.find((u) => u.id === user.id); const isAuthor = report.userId === user.id; - const canWriteReport = isCollaborator || isAuthor; + const canWriteReport = (isCollaborator || isAuthor) + && (report.status === REPORT_STATUSES.DRAFT + || report.status === REPORT_STATUSES.NEEDS_ACTION); updateAdditionalData({ recipients, collaborators, approvers }); updateFormData(report); updateApprovingManager(report.approvingManagerId === user.id); - updateCanWrite(canWriteReport); + updateEditable(canWriteReport); if (showLastUpdatedTime) { updateInitialLastUpdated(moment(report.updatedAt)); @@ -151,10 +154,15 @@ function ActivityReport({ match, user, location }) { ); } + if (!editable && currentPage !== 'review') { + return ( + + ); + } + if (!currentPage) { - const defaultPage = formData.status === REPORT_STATUSES.DRAFT ? 'activity-summary' : 'review'; return ( - + ); } @@ -170,28 +178,28 @@ function ActivityReport({ match, user, location }) { const onSave = async (data, newIndex) => { const { activityRecipientType, activityRecipients } = data; let updatedReport = false; - if (canWrite) { - if (reportId.current === 'new') { - if (activityRecipientType && activityRecipients && activityRecipients.length > 0) { - const savedReport = await createReport({ ...data, regionId: region }, {}); - reportId.current = savedReport.id; - updatedReport = false; - } - } else { - await saveReport(reportId.current, data, {}); - updatedReport = true; + if (reportId.current === 'new') { + if (activityRecipientType && activityRecipients && activityRecipients.length > 0) { + const savedReport = await createReport({ ...data, regionId: region }, {}); + reportId.current = savedReport.id; + updatedReport = false; } + } else { + await saveReport(reportId.current, data, {}); + updatedReport = true; } if (newIndex) { updatePage(newIndex); } + return updatedReport; }; const onFormSubmit = async (data) => { const report = await submitReport(reportId.current, data); updateFormData(report); + updateEditable(false); }; const onReview = async (data) => { @@ -199,11 +207,18 @@ function ActivityReport({ match, user, location }) { updateFormData(report); }; + const onResetToDraft = async () => { + const report = await resetToDraft(reportId.current); + updateFormData(report); + updateEditable(true); + }; + return ( <>

New activity report for Region 14

diff --git a/src/policies/activityReport.js b/src/policies/activityReport.js index 6e341962f7..1b482c1dc7 100644 --- a/src/policies/activityReport.js +++ b/src/policies/activityReport.js @@ -25,7 +25,14 @@ export default class ActivityReport { } canUpdate() { - return (this.isAuthor() || this.isCollaborator()) && this.canWriteInRegion(); + return (this.isAuthor() || this.isCollaborator()) + && this.canWriteInRegion() + && this.reportHasEditableStatus(); + } + + canReset() { + return (this.isAuthor || this.isCollaborator) + && this.activityReport.status === REPORT_STATUSES.SUBMITTED; } canGet() { @@ -71,4 +78,9 @@ export default class ActivityReport { isApprovingManager() { return this.activityReport.approvingManagerId === this.user.id; } + + reportHasEditableStatus() { + return this.activityReport.status === REPORT_STATUSES.DRAFT + || this.activityReport.status === REPORT_STATUSES.NEEDS_ACTION; + } } diff --git a/src/policies/activityReport.test.js b/src/policies/activityReport.test.js index 73346dcb6e..f329078ae3 100644 --- a/src/policies/activityReport.test.js +++ b/src/policies/activityReport.test.js @@ -84,6 +84,12 @@ describe('Activity Report policies', () => { expect(policy.canUpdate()).toBeTruthy(); }); + it('is true if the user is the author and report status is NEEDS_ACTION', () => { + const report = activityReport(author.id, null, REPORT_STATUSES.NEEDS_ACTION); + const policy = new ActivityReport(author, report); + expect(policy.canUpdate()).toBeTruthy(); + }); + it('is true if the user is a collaborator', () => { const report = activityReport(author.id, collaborator); const policy = new ActivityReport(collaborator, report); @@ -102,6 +108,18 @@ describe('Activity Report policies', () => { const policy = new ActivityReport(otherUser, report); expect(policy.canUpdate()).toBeFalsy(); }); + + it('is false if the report has been submitted', () => { + const report = activityReport(author.id, null, REPORT_STATUSES.SUBMITTED); + const policy = new ActivityReport(author, report); + expect(policy.canUpdate()).toBeFalsy(); + }); + + it('is false if the report has been approved', () => { + const report = activityReport(author.id, null, REPORT_STATUSES.APPROVED); + const policy = new ActivityReport(author, report); + expect(policy.canUpdate()).toBeFalsy(); + }); }); describe('canGet', () => { diff --git a/src/routes/activityReports/handlers.js b/src/routes/activityReports/handlers.js index 8ef9027c53..05f8f001a5 100644 --- a/src/routes/activityReports/handlers.js +++ b/src/routes/activityReports/handlers.js @@ -3,7 +3,7 @@ import SCOPES from '../../middleware/scopeConstants'; import ActivityReport from '../../policies/activityReport'; import User from '../../policies/user'; import { - possibleRecipients, activityReportById, createOrUpdate, review, activityReports, + possibleRecipients, activityReportById, createOrUpdate, review, activityReports, setStatus, } from '../../services/activityReports'; import { goalsForGrants } from '../../services/goals'; import { userById, usersWithPermissions } from '../../services/users'; @@ -85,6 +85,26 @@ export async function reviewReport(req, res) { } } +export async function resetToDraft(req, res) { + try { + const { activityReportId } = req.params; + + const user = await userById(req.session.userId); + const report = await activityReportById(activityReportId); + const authorization = new ActivityReport(user, report); + + if (!authorization.canReset()) { + res.sendStatus(403); + return; + } + + const savedReport = await setStatus(report, REPORT_STATUSES.DRAFT); + res.json(savedReport); + } catch (error) { + await handleErrors(req, res, error, logContext); + } +} + /** * Flags a report as submitted for approval * diff --git a/src/routes/activityReports/index.js b/src/routes/activityReports/index.js index adb0024595..9cfe440be3 100644 --- a/src/routes/activityReports/index.js +++ b/src/routes/activityReports/index.js @@ -9,6 +9,7 @@ import { getActivityRecipients, getGoals, reviewReport, + resetToDraft, } from './handlers'; const router = express.Router(); @@ -24,6 +25,7 @@ router.get('/goals', getGoals); router.get('/:activityReportId', getReport); router.get('/', getReports); router.put('/:activityReportId', saveReport); +router.put('/:activityReportId/reset', resetToDraft); router.put('/:activityReportId/review', reviewReport); router.post('/:activityReportId/submit', submitReport); diff --git a/src/services/activityReports.js b/src/services/activityReports.js index e90b69b805..94ef608461 100644 --- a/src/services/activityReports.js +++ b/src/services/activityReports.js @@ -152,6 +152,11 @@ export function activityReportById(activityReportId) { }, ], }, + { + model: User, + as: 'author', + attributes: ['name'], + }, { model: Goal, as: 'goals', @@ -245,6 +250,7 @@ export async function createOrUpdate(newActivityReport, report) { attachments, otherResources, approvingManager, + author, ...updatedFields } = newActivityReport; await sequelize.transaction(async (transaction) => { @@ -273,6 +279,13 @@ export async function createOrUpdate(newActivityReport, report) { return activityReportById(savedReport.id); } +export async function setStatus(report, status) { + const updatedReport = await report.update({ status }, { + fields: ['status'], + }); + return updatedReport; +} + export async function possibleRecipients() { const grants = await Grantee.findAll({ attributes: ['id', 'name'], From 42012b2e76d6a3eba08bf65acbc3147cb36d59da Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Wed, 17 Feb 2021 21:12:30 -0600 Subject: [PATCH 2/6] Update and add some tests --- .../components/Navigator/__tests__/index.js | 1 + .../Pages/Review/Approver/__tests__/index.js | 10 +++++-- .../Pages/Review/Approver/index.js | 4 ++- .../Pages/Review/Submitter/Draft.js | 10 ------- .../Pages/Review/Submitter/__tests__/index.js | 29 ++++++++++++++----- .../Pages/Review/__tests__/index.js | 11 +++---- .../pages/ActivityReport/__tests__/index.js | 15 ++++++++-- 7 files changed, 51 insertions(+), 29 deletions(-) diff --git a/frontend/src/components/Navigator/__tests__/index.js b/frontend/src/components/Navigator/__tests__/index.js index 58365a0530..7a0dc95b9c 100644 --- a/frontend/src/components/Navigator/__tests__/index.js +++ b/frontend/src/components/Navigator/__tests__/index.js @@ -61,6 +61,7 @@ describe('Navigator', () => { const renderNavigator = (currentPage = 'first', onSubmit = () => {}, onSave = () => {}) => { render( + > +
+ ); }; const renderReview = (status, onFormReview, reviewed, valid, notes = '') => { const formData = { approvingManager: { name: 'name' }, + author: { name: 'user' }, managerNotes: notes, additionalNotes: notes, approvingManagerId: '1', @@ -61,8 +64,9 @@ describe('Approver review page', () => { userEvent.selectOptions(dropdown, 'approved'); const button = await screen.findByRole('button'); userEvent.click(button); - const alert = await screen.findByTestId('alert'); - expect(alert.textContent).toContain('Success'); + const alerts = await screen.findAllByTestId('alert'); + const success = alerts.find((alert) => alert.textContent.includes('Success')); + expect(success).toBeVisible(); expect(mockSubmit).toHaveBeenCalled(); }); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js index 71d8b84a3e..6be5824ec9 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js @@ -93,7 +93,9 @@ Approver.propTypes = { managerNotes: PropTypes.string, additionalNotes: PropTypes.string, status: PropTypes.string, - author: PropTypes.string, + author: PropTypes.shape({ + name: PropTypes.string, + }), }).isRequired, }; diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js index bf2543689a..8ca703d264 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js @@ -8,7 +8,6 @@ import { import { DECIMAL_BASE } from '../../../../../Constants'; const Draft = ({ - submitted, allComplete, register, approvers, @@ -24,14 +23,6 @@ const Draft = ({ }; return ( <> - {submitted - && ( - - Success -
- This report was successfully submitted for approval -
- )} {!allComplete && ( @@ -67,7 +58,6 @@ const Draft = ({ }; Draft.propTypes = { - submitted: PropTypes.bool.isRequired, allComplete: PropTypes.bool.isRequired, register: PropTypes.func.isRequired, approvers: PropTypes.arrayOf(PropTypes.shape({ diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js index 00904e1a0c..663e740731 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js @@ -9,7 +9,7 @@ import { REPORT_STATUSES } from '../../../../../../Constants'; const RenderSubmitter = ({ // eslint-disable-next-line react/prop-types - submitted, allComplete, onFormSubmit, formData, valid, + submitted, allComplete, onFormSubmit, formData, valid, onResetToDraft, }) => { const { register, handleSubmit } = useForm({ mode: 'onChange', @@ -21,6 +21,7 @@ const RenderSubmitter = ({ submitted={submitted} allComplete={allComplete} onFormSubmit={onFormSubmit} + onResetToDraft={onResetToDraft} register={register} handleSubmit={handleSubmit} valid={valid} @@ -30,7 +31,7 @@ const RenderSubmitter = ({ ); }; -const renderReview = (status, submitted, allComplete, onFormSubmit) => { +const renderReview = (status, submitted, allComplete, onFormSubmit, resetToDraft = () => {}) => { const formData = { approvingManager: { name: 'name' }, approvingManagerId: 1, @@ -44,6 +45,7 @@ const renderReview = (status, submitted, allComplete, onFormSubmit) => { allComplete={allComplete} onFormSubmit={onFormSubmit} formData={formData} + onResetToDraft={resetToDraft} valid />, ); @@ -69,12 +71,6 @@ describe('Submitter review page', () => { const alert = await screen.findByTestId('alert'); expect(alert.textContent).toContain('Incomplete report'); }); - - it('displays success if the report has been submitted', async () => { - renderReview(REPORT_STATUSES.DRAFT, true, true, () => {}); - const alert = await screen.findByTestId('alert'); - expect(alert.textContent).toContain('Success'); - }); }); describe('when the report is approved', () => { @@ -84,6 +80,23 @@ describe('Submitter review page', () => { }); }); + describe('when the report has been submitted', () => { + it('displays the submitted page', async () => { + renderReview(REPORT_STATUSES.SUBMITTED, false, true, () => {}); + const allAlerts = await screen.findAllByTestId('alert'); + const successAlert = allAlerts.find((alert) => alert.textContent.includes('Success')); + expect(successAlert).toBeVisible(); + }); + + it('the reset to draft button works', async () => { + const onReset = jest.fn(); + renderReview(REPORT_STATUSES.SUBMITTED, false, true, () => {}, onReset); + const button = await screen.findByRole('button', { name: 'Reset to Draft' }); + userEvent.click(button); + await waitFor(() => expect(onReset).toHaveBeenCalled()); + }); + }); + describe('when the report needs action', () => { it('displays the needs action component', async () => { renderReview(REPORT_STATUSES.NEEDS_ACTION, false, true, () => {}); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js index 96330aa66c..adc72bab3b 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js @@ -31,6 +31,7 @@ const RenderReview = ({ approvers={approvers} formData={formData} onReview={onReview} + onResetToDraft={() => {}} approvingManager={approvingManager} /> @@ -50,7 +51,7 @@ const renderReview = ( { userEvent.selectOptions(screen.getByTestId('dropdown'), ['approved']); const reviewButton = await screen.findByRole('button'); userEvent.click(reviewButton); - const error = await screen.findByTestId('alert'); - expect(error).toHaveTextContent('Unable to review report'); + const error = await screen.findByText('Unable to review report'); + expect(error).toBeVisible(); }); }); @@ -143,8 +144,8 @@ describe('ReviewSubmit', () => { const button = await screen.findByRole('button'); expect(button).toBeEnabled(); userEvent.click(button); - const error = await screen.findByTestId('alert'); - expect(error).toHaveTextContent('Unable to submit report'); + const error = await screen.findByText('Unable to submit report'); + expect(error).toBeVisible(); }); }); diff --git a/frontend/src/pages/ActivityReport/__tests__/index.js b/frontend/src/pages/ActivityReport/__tests__/index.js index 28533a7a94..1a5573983c 100644 --- a/frontend/src/pages/ActivityReport/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/__tests__/index.js @@ -36,12 +36,14 @@ const formData = () => ({ resourcesUsed: 'eclkcurl', startDate: moment().format('MM/DD/YYYY'), targetPopulations: ['target 1'], + author: { name: 'test' }, topics: 'first', + userId: 1, updatedAt: new Date().toISOString(), }); const history = createMemoryHistory(); -const renderActivityReport = (id, location = 'activity-summary', showLastUpdatedTime = null) => { +const renderActivityReport = (id, location = 'activity-summary', showLastUpdatedTime = null, userId = 1) => { render( , ); @@ -69,6 +71,15 @@ describe('ActivityReport', () => { fetchMock.get('/api/activity-reports/approvers?region=1', []); }); + describe('for read only users', () => { + it('redirects the user to the review page', async () => { + const data = formData(); + fetchMock.get('/api/activity-reports/1', data); + renderActivityReport('1', null, null, 2); + await waitFor(() => expect(history.location.pathname).toEqual('/activity-reports/1/review')); + }); + }); + describe('last saved time', () => { it('is shown if history.state.showLastUpdatedTime is true', async () => { const data = formData(); From 56770415096ea49bc363b95966655b5aed71b825 Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Mon, 22 Feb 2021 16:03:18 -0600 Subject: [PATCH 3/6] Add API doc for reset --- .../openapi/paths/activity-reports/reset.yaml | 21 +++++++++++++++++++ docs/openapi/paths/index.yaml | 2 ++ .../Pages/Review/Submitter/Draft.js | 12 +---------- 3 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 docs/openapi/paths/activity-reports/reset.yaml diff --git a/docs/openapi/paths/activity-reports/reset.yaml b/docs/openapi/paths/activity-reports/reset.yaml new file mode 100644 index 0000000000..ba6f0b1a1e --- /dev/null +++ b/docs/openapi/paths/activity-reports/reset.yaml @@ -0,0 +1,21 @@ +put: + tags: + - activity-reports + summary: Reset activity report to draft + description: > + Activity reports are not editable when submitted for approval. This + endpoint allows a user to reset a report back to draft mode so that + the report can be edited. + parameters: + - in: path + name: activityReportId + required: true + schema: + type: number + responses: + 200: + description: The report that now has a status of "draft" + content: + application/json: + schema: + $ref: '../../index.yaml#/components/schemas/activityReport' \ No newline at end of file diff --git a/docs/openapi/paths/index.yaml b/docs/openapi/paths/index.yaml index fa9e905dfe..785326ecb0 100644 --- a/docs/openapi/paths/index.yaml +++ b/docs/openapi/paths/index.yaml @@ -26,5 +26,7 @@ $ref: './activity-reports/submit.yaml' '/activity-reports/{activityReportId}/review': $ref: './activity-reports/review.yaml' +'/activity-reports/{activityReportId}/reset': + $ref: './activity-reports/reset.yaml' '/files': $ref: './files.yaml' diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js index ccc9dbae7f..d9ea673414 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/Draft.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useFormContext } from 'react-hook-form'; import { - Dropdown, Form, Fieldset, Textarea, Alert, Button, + Dropdown, Form, Fieldset, Textarea, Button, } from '@trussworks/react-uswds'; import IncompletePages from './IncompletePages'; @@ -10,7 +10,6 @@ import { DECIMAL_BASE } from '../../../../../Constants'; import FormItem from '../../../../../components/FormItem'; const Draft = ({ - submitted, approvers, onFormSubmit, onSaveForm, @@ -36,14 +35,6 @@ const Draft = ({ return ( <> - {submitted - && ( - - Success -
- This report was successfully submitted for approval -
- )}

Submit Report

@@ -82,7 +73,6 @@ const Draft = ({ }; Draft.propTypes = { - submitted: PropTypes.bool.isRequired, onSaveForm: PropTypes.func.isRequired, approvers: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number, From a8eade7b3cda33861950c592e87db6c950c55abb Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Mon, 22 Feb 2021 17:09:23 -0600 Subject: [PATCH 4/6] Update tests --- .../Pages/Review/Submitter/__tests__/index.js | 44 ++++++++----------- .../Pages/Review/__tests__/index.js | 7 --- .../ActivityReport/Pages/Review/index.js | 1 + src/policies/activityReport.test.js | 21 +++++++++ src/routes/activityReports/handlers.test.js | 29 +++++++++++- 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js index 0700dc870c..e7b1d36b7a 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js @@ -10,7 +10,7 @@ import { REPORT_STATUSES } from '../../../../../../Constants'; const RenderSubmitter = ({ // eslint-disable-next-line react/prop-types - submitted, onFormSubmit, formData, pages, onResetToDraft, onSave, + onFormSubmit, formData, pages, onResetToDraft, onSave, }) => { const hookForm = useForm({ mode: 'onChange', @@ -20,13 +20,15 @@ const RenderSubmitter = ({ return ( + > +
+ ); }; @@ -45,7 +47,6 @@ const incompletePages = [{ const renderReview = ( status, - submitted, onFormSubmit, complete = true, onSave = () => {}, @@ -61,7 +62,6 @@ const renderReview = ( render( { describe('when the report is a draft', () => { it('displays the draft review component', async () => { - renderReview(REPORT_STATUSES.DRAFT, false, () => {}); + renderReview(REPORT_STATUSES.DRAFT, () => {}); expect(await screen.findByText('Submit Report')).toBeVisible(); }); it('allows the author to submit for review', async () => { const mockSubmit = jest.fn(); - renderReview(REPORT_STATUSES.DRAFT, false, mockSubmit); + renderReview(REPORT_STATUSES.DRAFT, mockSubmit); const button = await screen.findByRole('button', { name: 'Submit for approval' }); userEvent.click(button); await waitFor(() => expect(mockSubmit).toHaveBeenCalled()); }); it('displays an error if the report is not complete', async () => { - renderReview(REPORT_STATUSES.DRAFT, false, () => {}, false); + renderReview(REPORT_STATUSES.DRAFT, () => {}, false); const alert = await screen.findByTestId('alert'); expect(alert.textContent).toContain('Incomplete report'); }); it('shows pages that are not completed', async () => { - renderReview(REPORT_STATUSES.DRAFT, false, () => {}, false); + renderReview(REPORT_STATUSES.DRAFT, () => {}, false); const alert = await screen.findByText('Incomplete report'); expect(alert).toBeVisible(); }); it('fails to submit if there are pages that have not been completed', async () => { const mockSubmit = jest.fn(); - renderReview(REPORT_STATUSES.DRAFT, false, mockSubmit, false); + renderReview(REPORT_STATUSES.DRAFT, mockSubmit, false); const button = await screen.findByRole('button', { name: 'Submit for approval' }); userEvent.click(button); await waitFor(() => expect(mockSubmit).not.toHaveBeenCalled()); }); - it('displays success if the report has been submitted', async () => { - renderReview(REPORT_STATUSES.DRAFT, true, () => {}); - const alert = await screen.findByTestId('alert'); - expect(alert.textContent).toContain('Success'); - }); - - it('a draft can be saved', async () => { + it('can be saved', async () => { const mockSave = jest.fn(); - renderReview(REPORT_STATUSES.DRAFT, false, () => {}, true, mockSave); + renderReview(REPORT_STATUSES.DRAFT, () => {}, true, mockSave); const button = await screen.findByRole('button', { name: 'Save Draft' }); userEvent.click(button); await waitFor(() => expect(mockSave).toHaveBeenCalled()); @@ -123,14 +117,14 @@ describe('Submitter review page', () => { describe('when the report is approved', () => { it('displays the approved component', async () => { - renderReview(REPORT_STATUSES.APPROVED, false, () => {}); + renderReview(REPORT_STATUSES.APPROVED, () => {}); expect(await screen.findByText('Report approved')).toBeVisible(); }); }); describe('when the report has been submitted', () => { it('displays the submitted page', async () => { - renderReview(REPORT_STATUSES.SUBMITTED, false, true, () => {}); + renderReview(REPORT_STATUSES.SUBMITTED, true, () => {}); const allAlerts = await screen.findAllByTestId('alert'); const successAlert = allAlerts.find((alert) => alert.textContent.includes('Success')); expect(successAlert).toBeVisible(); @@ -147,19 +141,19 @@ describe('Submitter review page', () => { describe('when the report needs action', () => { it('displays the needs action component', async () => { - renderReview(REPORT_STATUSES.NEEDS_ACTION, false, () => {}); + renderReview(REPORT_STATUSES.NEEDS_ACTION, () => {}); expect(await screen.findByText('Review and re-submit report')).toBeVisible(); }); it('shows pages that are not completed', async () => { - renderReview(REPORT_STATUSES.NEEDS_ACTION, false, () => {}, false); + renderReview(REPORT_STATUSES.NEEDS_ACTION, () => {}, false); const alert = await screen.findByText('Incomplete report'); expect(alert).toBeVisible(); }); it('fails to re-submit if there are pages that have not been completed', async () => { const mockSubmit = jest.fn(); - renderReview(REPORT_STATUSES.NEEDS_ACTION, false, mockSubmit, false); + renderReview(REPORT_STATUSES.NEEDS_ACTION, mockSubmit, false); const button = await screen.findByRole('button'); userEvent.click(button); await waitFor(() => expect(mockSubmit).not.toHaveBeenCalled()); @@ -167,7 +161,7 @@ describe('Submitter review page', () => { it('allows the user to resubmit the report', async () => { const mockSubmit = jest.fn(); - renderReview(REPORT_STATUSES.NEEDS_ACTION, false, mockSubmit); + renderReview(REPORT_STATUSES.NEEDS_ACTION, mockSubmit); const button = await screen.findByRole('button'); userEvent.click(button); await waitFor(() => expect(mockSubmit).toHaveBeenCalled()); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js index 35366a0e0e..90fadd5959 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js @@ -159,13 +159,6 @@ describe('ReviewSubmit', () => { }); }); - it('a success modal is shown once submitted', async () => { - renderReview(true, false, REPORT_STATUSES.DRAFT, {}, () => {}, () => {}, 1); - userEvent.click(await screen.findByRole('button', { name: 'Submit for approval' })); - const alert = await screen.findByTestId('alert'); - expect(alert).toHaveClass('usa-alert--success'); - }); - it('initializes the form with "initialData"', async () => { renderReview(true, false, REPORT_STATUSES.DRAFT, { additionalNotes: 'test' }); const textBox = await screen.findByLabelText('Creator notes'); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/index.js b/frontend/src/pages/ActivityReport/Pages/Review/index.js index 6ec062efd9..2de11f5f32 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/index.js @@ -84,6 +84,7 @@ const ReviewSubmit = ({ reviewed={reviewed} additionalNotes={additionalNotes} onFormReview={onFormReview} + error={error} formData={formData} > diff --git a/src/policies/activityReport.test.js b/src/policies/activityReport.test.js index f329078ae3..8e07892706 100644 --- a/src/policies/activityReport.test.js +++ b/src/policies/activityReport.test.js @@ -122,6 +122,27 @@ describe('Activity Report policies', () => { }); }); + describe('canReset', () => { + it('is false for reports that have not been submitted', async () => { + const report = activityReport(author.id, null, REPORT_STATUSES.APPROVED); + const policy = new ActivityReport(author, report); + expect(policy.canReset()).toBeFalsy(); + }); + + it('is true for the author', async () => { + const report = activityReport(author.id, null, REPORT_STATUSES.SUBMITTED); + const policy = new ActivityReport(author, report); + expect(policy.canReset()).toBeTruthy(); + + }); + + it('is true for collaborators', async () => { + const report = activityReport(author.id, collaborator, REPORT_STATUSES.SUBMITTED); + const policy = new ActivityReport(collaborator, report); + expect(policy.canReset()).toBeTruthy(); + }); + }); + describe('canGet', () => { describe('for unapproved reports', () => { it('is true for the author', () => { diff --git a/src/routes/activityReports/handlers.test.js b/src/routes/activityReports/handlers.test.js index 2e78260f2a..5228eb806e 100644 --- a/src/routes/activityReports/handlers.test.js +++ b/src/routes/activityReports/handlers.test.js @@ -6,9 +6,10 @@ import { getApprovers, submitReport, reviewReport, + resetToDraft, } from './handlers'; import { - activityReportById, createOrUpdate, possibleRecipients, review, + activityReportById, createOrUpdate, possibleRecipients, review, setStatus, } from '../../services/activityReports'; import { userById, usersWithPermissions } from '../../services/users'; import ActivityReport from '../../policies/activityReport'; @@ -19,6 +20,7 @@ jest.mock('../../services/activityReports', () => ({ createOrUpdate: jest.fn(), possibleRecipients: jest.fn(), review: jest.fn(), + setStatus: jest.fn(), })); jest.mock('../../services/users', () => ({ @@ -263,4 +265,29 @@ describe('Activity Report handlers', () => { expect(mockResponse.sendStatus).toHaveBeenCalledWith(403); }); }); + + describe('resetToDraft', () => { + const request = { + ...mockRequest, + params: { activityReportId: 1 }, + }; + + it('returns the updated report', async () => { + const result = { status: 'draft' } + ActivityReport.mockImplementation(() => ({ + canReset: () => true, + })); + setStatus.mockResolvedValue(result); + await resetToDraft(request, mockResponse); + expect(mockResponse.json).toHaveBeenCalledWith(result); + }); + + it('handles unauthorized', async () => { + ActivityReport.mockImplementation(() => ({ + canReset: () => false, + })); + await resetToDraft(request, mockResponse); + expect(mockResponse.sendStatus).toHaveBeenCalledWith(403); + }); + }); }); From f821fa534cc5b24e3ca0394e74707f8166e8df36 Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Mon, 22 Feb 2021 17:12:53 -0600 Subject: [PATCH 5/6] lint fixes --- src/policies/activityReport.test.js | 1 - src/routes/activityReports/handlers.test.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/policies/activityReport.test.js b/src/policies/activityReport.test.js index 8e07892706..32a7324eb1 100644 --- a/src/policies/activityReport.test.js +++ b/src/policies/activityReport.test.js @@ -133,7 +133,6 @@ describe('Activity Report policies', () => { const report = activityReport(author.id, null, REPORT_STATUSES.SUBMITTED); const policy = new ActivityReport(author, report); expect(policy.canReset()).toBeTruthy(); - }); it('is true for collaborators', async () => { diff --git a/src/routes/activityReports/handlers.test.js b/src/routes/activityReports/handlers.test.js index 5228eb806e..a762f3ef7c 100644 --- a/src/routes/activityReports/handlers.test.js +++ b/src/routes/activityReports/handlers.test.js @@ -273,7 +273,7 @@ describe('Activity Report handlers', () => { }; it('returns the updated report', async () => { - const result = { status: 'draft' } + const result = { status: 'draft' }; ActivityReport.mockImplementation(() => ({ canReset: () => true, })); From 6fb4904ba8faaa0d6ec65842d7329cbc4e8123e2 Mon Sep 17 00:00:00 2001 From: Josh Salisbury Date: Wed, 24 Feb 2021 09:28:10 -0600 Subject: [PATCH 6/6] Prevent review page alerts from printing --- .../src/pages/ActivityReport/Pages/Review/Approver/index.js | 2 +- .../pages/ActivityReport/Pages/Review/Submitter/index.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js index 81ae173d81..adf9306727 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Approver/index.js @@ -20,7 +20,7 @@ const Approver = ({ const { author } = formData; const renderTopAlert = () => ( - + {review && ( <> diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js index ac4f2d31ef..3562a4e078 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/index.js @@ -37,7 +37,7 @@ const Submitter = ({ const renderTopAlert = () => ( <> {needsAction && ( - + { approvingManager.name } {' '} @@ -48,12 +48,12 @@ const Submitter = ({ )} {approved && ( - + This report has been approved and is no longer editable )} {submitted && ( - + Report is not editable
This report is no longer editable while it is waiting for manager approval.