Skip to content

Commit

Permalink
Merge pull request #139 from adhocteam/js-137-manager-approves-report
Browse files Browse the repository at this point in the history
Managers can add notes and set status of reports
  • Loading branch information
jasalisbury authored Feb 4, 2021
2 parents eb867ac + 75e4df0 commit d31f14f
Show file tree
Hide file tree
Showing 35 changed files with 538 additions and 104 deletions.
5 changes: 3 additions & 2 deletions docs/logical_data_model.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Logical Data Model
==================

<img src="http://www.plantuml.com/plantuml/png/nLVRRkCs47tNL_2jRO0OHOkYm29Ox6xgBV9GDqYo7p2M9Z9RYiCEHzaQSVwzffWAeYnd6QkNbmGwSpyyrCZll01BsvZ2bs1GVRluyOUY-4h10-bAEQQrmSQhpres2cnji58bqsUlxX6byBzhwu2XKKPRbAr3HImRAehIWFVgaqTMZuLIPqfNwetILh3UGnSNDLfa4ApUljsRDnvzyBqAJbvOstgFMcXm-EmsP77LDcla8Noci05jXf1eCVX6eMsRa9qQlC5QaxqQDF7rzzzzeswM7vStozNbybQvTcrqkOYEVg6hBdN96BfyB_j0qGrwWSPrbjPL4vQdlqUFUNA6FniDsgUuBSdXAHcKgj2Nh9reiZqwQvnhv4PxdprIwv4ps0w7tdFD9vwH3pnbX7Ly_XCd-qUBNfRCn3w73NBXGPCTdb3BUlZOe6meKJ_7CX-esgQmTsGz7iClgS8UdpaecIdvlIJPEtAwp8_foyIuB6KncPp33bdxivQG_ghwKapNnNo1_4nWyZXGoWj8wuT8I7ZF8pVjFp8rjmsm-0sYt0bS6mY2MXCP13klusxmbzgkzxOCqaEA_ujq1YkOgTVvbOxM6Q-dazzgTHmeX_Ne6GCF1TLj-9z0S3GeskeGdKrCa436HJvbm9IQtBWOTPA6Pt2n8XkxFcM1polzlXJze6LxWuvOSiepUcgvxBx1aXq4LQN3uWAp8i54LL7elzvV0uikjGjC9tUXGgCVaBU_76osgktNOOMbRi0aQWp39RBj8UWdsnVKQELkwt1YPuw_3m_lX6Eg6PeG7t1WXkr5j0P21BX6kIRNcgxJAHz6y6Gd32vbP6IEhyL9Wq2Svy1IaXNyKv81eCPRYUpyvicU_D5bmCkdAAWFst_vY-qvRBwq1wBBkrwGt8cCXjDB51j_rMidXjZ-DP0Hj-gTPnELjdz9ni2Q68Jul-BhjO8C8TFjvw-KkMsVi2cUsmuJgDtkd1vLb7f4dkZyVFSu-F5KnDzqXtYCcZAGwVsxJwMY-wkUTXqKUYYYQdgtVWyNuSy16bCk5Yhy7wISXcBHFji8YON3v7s9vr5IBEKv93ckq4ZToovVofVqUymKAHoPaxCScTB7n2Tv9qLUWdtQt5zqFExp3ctLDkOl">
<img src="http://www.plantuml.com/plantuml/png/nLVRRkCs47tNL_2jRO0OHOkYm29Ox6xgBV9GDqYo7p2M9Z9RYiCEHzaQSVwzefaAeYnd6QkNbmGwSpyylBXuvmLOsiOKlWI3wjl5ZpyKnLSA7aXNoZ6j3JPUVTQoKM1hWvKgcJvxTOyeXVzTMmSCZJBQecmTAcBPK56K1hnNdpooUYoKEbDTjZTAMy6wWoukQhJ885YzVTkPDnvzyBqAJbvOsxf3BJGu_7ORihXgcpNo43vJs80sGqYq67oZqBPDo4uDtc2joLuDclZw----KJVBZykRvUfoUQjSkpQwN4H7lz3LFdN96BfyBrsWw0QzGEFsbjPL4vQdlqUFUNA6FniDsgUuBSdXAHcKgj2Nh9reiZqwQvnhv4PxdprIwv4ps0wBtdFD9wwH3pnbXEtv_2TMze-smvRCn3w73NBXGvCThb3BUlZPe6meKJ_7CX-esgQmTsGz7iClgS8UdpaecIdvlIJPEtAwp8_foyIuB6KncPp53bdxjPQG_ghwKio-Y_a2-Pd0v76Wb1UGrW-HaF2UHsxQVsHgRXjWyHj4kHEuDX04jIOo27PMnt7PNcgxxcmPf8SK_nVf35OmKw_pAnsjCxwUJZxLwZXG3klHCmQE11KHbfz0S3GeskeGdKrCa43EHZvXm9IQtBWOTPA6Pt2n8XkxFkK2drVwVIdwGSls1Xsnv9HdzDHokN-39NSGL9KMJHRCYWGJLKMX_tf_3Iowr2umdUo52er-GDx-Sd2pLMr_7LPOwWPCeiOmN2BR7e9-igwWHYjtMuSJT-RuVNYu9nnJpT24-803CsmleZKG8i0roZMvrkmxdV9X14zsmk0IHiRcU2nE6WJYF0UMagpWdv8C03NUIcJdDq-sWngm7SZfIfty63FWvLCKseVjl_oIUmwRB_c16FEs7IHx9QFXT7F5nbzr7CKGsnyF6N6htdasKMdxbsGCh8b1YFyhlbuho10otNx-LJEtxHDkaEUsmmHgjpkdHnMb7f4dEZ_VFGv-L1NnjzuX7gEc36Hw__qJgeXlwAVT7Wez554rlLj_FnVXpm4QKouMAlmVf9o6Oj4-smY9XSFaVOddKL8ivJaaEQxGIDsBBb_Cb_Hxp1Gf79cJjHoPqi_49pcJ8Y_1FcqUF1gE-hn3MxMD-Gi0">

UML Source
----------
Expand Down Expand Up @@ -150,6 +150,7 @@ class ActivityReport {
ttaType : array<string>
context : string
pageState : json
managerNotes : string
* userId : integer(32) REFERENCES public.Users.id
* lastUpdatedById : integer(32) REFERENCES public.Users.id
* regionId : integer(32) REFERENCES public.Region.id
Expand Down Expand Up @@ -208,7 +209,7 @@ NonGrantee ||-{ ActivityParticipant
Instructions
------------

1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/uml/nLVRRkCs47tNL_2jRO0OHOkYm29Ox6xgBV9GDqYo7p2M9Z9RYiCEHzaQSVwzffWAeYnd6QkNbmGwSpyyrCZll01BsvZ2bs1GVRluyOUY-4h10-bAEQQrmSQhpres2cnji58bqsUlxX6byBzhwu2XKKPRbAr3HImRAehIWFVgaqTMZuLIPqfNwetILh3UGnSNDLfa4ApUljsRDnvzyBqAJbvOstgFMcXm-EmsP77LDcla8Noci05jXf1eCVX6eMsRa9qQlC5QaxqQDF7rzzzzeswM7vStozNbybQvTcrqkOYEVg6hBdN96BfyB_j0qGrwWSPrbjPL4vQdlqUFUNA6FniDsgUuBSdXAHcKgj2Nh9reiZqwQvnhv4PxdprIwv4ps0w7tdFD9vwH3pnbX7Ly_XCd-qUBNfRCn3w73NBXGPCTdb3BUlZOe6meKJ_7CX-esgQmTsGz7iClgS8UdpaecIdvlIJPEtAwp8_foyIuB6KncPp33bdxivQG_ghwKapNnNo1_4nWyZXGoWj8wuT8I7ZF8pVjFp8rjmsm-0sYt0bS6mY2MXCP13klusxmbzgkzxOCqaEA_ujq1YkOgTVvbOxM6Q-dazzgTHmeX_Ne6GCF1TLj-9z0S3GeskeGdKrCa436HJvbm9IQtBWOTPA6Pt2n8XkxFcM1polzlXJze6LxWuvOSiepUcgvxBx1aXq4LQN3uWAp8i54LL7elzvV0uikjGjC9tUXGgCVaBU_76osgktNOOMbRi0aQWp39RBj8UWdsnVKQELkwt1YPuw_3m_lX6Eg6PeG7t1WXkr5j0P21BX6kIRNcgxJAHz6y6Gd32vbP6IEhyL9Wq2Svy1IaXNyKv81eCPRYUpyvicU_D5bmCkdAAWFst_vY-qvRBwq1wBBkrwGt8cCXjDB51j_rMidXjZ-DP0Hj-gTPnELjdz9ni2Q68Jul-BhjO8C8TFjvw-KkMsVi2cUsmuJgDtkd1vLb7f4dkZyVFSu-F5KnDzqXtYCcZAGwVsxJwMY-wkUTXqKUYYYQdgtVWyNuSy16bCk5Yhy7wISXcBHFji8YON3v7s9vr5IBEKv93ckq4ZToovVofVqUymKAHoPaxCScTB7n2Tv9qLUWdtQt5zqFExp3ctLDkOl)
1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/png/nLVRRkCs47tNL_2jRO0OHOkYm29Ox6xgBV9GDqYo7p2M9Z9RYiCEHzaQSVwzefaAeYnd6QkNbmGwSpyylBXuvmLOsiOKlWI3wjl5ZpyKnLSA7aXNoZ6j3JPUVTQoKM1hWvKgcJvxTOyeXVzTMmSCZJBQecmTAcBPK56K1hnNdpooUYoKEbDTjZTAMy6wWoukQhJ885YzVTkPDnvzyBqAJbvOsxf3BJGu_7ORihXgcpNo43vJs80sGqYq67oZqBPDo4uDtc2joLuDclZw----KJVBZykRvUfoUQjSkpQwN4H7lz3LFdN96BfyBrsWw0QzGEFsbjPL4vQdlqUFUNA6FniDsgUuBSdXAHcKgj2Nh9reiZqwQvnhv4PxdprIwv4ps0wBtdFD9wwH3pnbXEtv_2TMze-smvRCn3w73NBXGvCThb3BUlZPe6meKJ_7CX-esgQmTsGz7iClgS8UdpaecIdvlIJPEtAwp8_foyIuB6KncPp53bdxjPQG_ghwKio-Y_a2-Pd0v76Wb1UGrW-HaF2UHsxQVsHgRXjWyHj4kHEuDX04jIOo27PMnt7PNcgxxcmPf8SK_nVf35OmKw_pAnsjCxwUJZxLwZXG3klHCmQE11KHbfz0S3GeskeGdKrCa43EHZvXm9IQtBWOTPA6Pt2n8XkxFkK2drVwVIdwGSls1Xsnv9HdzDHokN-39NSGL9KMJHRCYWGJLKMX_tf_3Iowr2umdUo52er-GDx-Sd2pLMr_7LPOwWPCeiOmN2BR7e9-igwWHYjtMuSJT-RuVNYu9nnJpT24-803CsmleZKG8i0roZMvrkmxdV9X14zsmk0IHiRcU2nE6WJYF0UMagpWdv8C03NUIcJdDq-sWngm7SZfIfty63FWvLCKseVjl_oIUmwRB_c16FEs7IHx9QFXT7F5nbzr7CKGsnyF6N6htdasKMdxbsGCh8b1YFyhlbuho10otNx-LJEtxHDkaEUsmmHgjpkdHnMb7f4dEZ_VFGv-L1NnjzuX7gEc36Hw__qJgeXlwAVT7Wez554rlLj_FnVXpm4QKouMAlmVf9o6Oj4-smY9XSFaVOddKL8ivJaaEQxGIDsBBb_Cb_Hxp1Gf79cJjHoPqi_49pcJ8Y_1FcqUF1gE-hn3MxMD-Gi0)
2. Copy and paste the final UML into the UML Source section
3. Update the img src and edit link target to the current values

Expand Down
46 changes: 46 additions & 0 deletions docs/openapi/paths/activity-reports/review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
put:
tags:
- activity-reports
summary: Review an activity report
description: >
An approving manager reviews an activity report to determine if it requires
any additional updates. If the report needs updates the manager sets the status to
'Needs Action', otherwise to 'Approved'
requestBody:
description: The status and any manager notes
required: true
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: The status of the report after review
enum:
- Approved
- Needs Action
managerNotes:
type: string
description: Any notes the manager needs to relay to the author/collaborators of the report
parameters:
- in: path
name: activityReportId
required: true
schema:
type: number
responses:
200:
description: The new status of the activity report
content:
application/json:
schema:
type: object
properties:
status:
type: string
enum:
- Approved
- Needs Action
managerNotes:
type: string
2 changes: 1 addition & 1 deletion docs/openapi/paths/collaborators.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ get:
schema:
type: array
items:
$ref: '../../index.yaml#/components/schemas/selectableUser'
$ref: '../index.yaml#/components/schemas/selectableUser'
2 changes: 2 additions & 0 deletions docs/openapi/paths/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@
$ref: './activity-reports/activity-reports-id.yaml'
'/activity-reports/{activityReportId}/submit':
$ref: './activity-reports/submit.yaml'
'/activity-reports/{activityReportId}/review':
$ref: './activity-reports/review.yaml'
'/files':
$ref: './files.yaml'
2 changes: 1 addition & 1 deletion frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function App() {
<Route
path="/activity-reports/:activityReportId/:currentPage?"
render={({ match }) => (
<ActivityReport match={match} />
<ActivityReport match={match} user={user} />
)}
/>
{admin
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,5 @@ export const REGIONS = [
11,
12,
];

export const DECIMAL_BASE = 10;
5 changes: 4 additions & 1 deletion frontend/src/components/Navigator/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const pages = [
label: 'review page',
path: 'review',
review: true,
render: (hookForm, allComplete, formData, submitted, onSubmit) => (
render: (hookForm, allComplete, formData, onSubmit) => (
<div>
<button type="button" data-testid="review" onClick={onSubmit}>Continue</button>
</div>
Expand All @@ -59,6 +59,9 @@ describe('Navigator', () => {
<Navigator
submitted={false}
initialData={initialData}
status="draft"
onReview={() => {}}
approvingManager={false}
defaultValues={{ first: '', second: '' }}
pages={pages}
currentPage={currentPage}
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/Navigator/components/SideNav.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@
color: #f8f8f8;
}

.smart-hub--tag-needs-action {
background-color: #f9e0e4;
color: #d42240;
}

.smart-hub--tag {
width: 84px;
width: 94px;
text-align: center;
font-weight: normal;
display: inline-block;
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/components/Navigator/components/SideNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import moment from 'moment';
import Container from '../../Container';
import './SideNav.css';
import {
NOT_STARTED, IN_PROGRESS, COMPLETE, SUBMITTED,
NOT_STARTED, IN_PROGRESS, COMPLETE, SUBMITTED, APPROVED, NEEDS_ACTION,
} from '../constants';

const tagClass = (state) => {
Expand All @@ -26,6 +26,10 @@ const tagClass = (state) => {
return 'smart-hub--tag-complete';
case SUBMITTED:
return 'smart-hub--tag-submitted';
case APPROVED:
return 'smart-hub--tag-submitted';
case NEEDS_ACTION:
return 'smart-hub--tag-needs-action';
default:
return '';
}
Expand All @@ -46,7 +50,7 @@ function SideNav({
>
<span className="margin-left-2">{page.label}</span>
<span className="margin-left-auto margin-right-2">
{page.state
{page.state !== 'draft'
&& (
<Tag className={`smart-hub--tag ${tagClass(page.state)}`}>
{page.state}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/Navigator/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export const NOT_STARTED = 'Not started';
export const IN_PROGRESS = 'In progress';
export const COMPLETE = 'Complete';
export const SUBMITTED = 'Submitted';
export const APPROVED = 'Approved';
export const NEEDS_ACTION = 'Needs Action';
16 changes: 10 additions & 6 deletions frontend/src/components/Navigator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import moment from 'moment';
import Container from '../Container';

import {
IN_PROGRESS, COMPLETE, SUBMITTED,
IN_PROGRESS, COMPLETE,
} from './constants';
import SideNav from './components/SideNav';
import NavigatorHeader from './components/NavigatorHeader';
Expand All @@ -24,11 +24,13 @@ function Navigator({
initialData,
pages,
onFormSubmit,
submitted,
onReview,
currentPage,
additionalData,
onSave,
autoSaveInterval,
approvingManager,
status,
reportId,
}) {
const [formData, updateFormData] = useState(initialData);
Expand All @@ -37,7 +39,6 @@ function Navigator({
const { pageState } = formData;

const page = pages.find((p) => p.path === currentPage);
const submittedNavState = submitted ? SUBMITTED : null;
const allComplete = _.every(pageState, (state) => state === COMPLETE);

const hookForm = useForm({
Expand Down Expand Up @@ -102,7 +103,7 @@ function Navigator({
const navigatorPages = pages.map((p) => {
const current = p.position === page.position;
const stateOfPage = current ? IN_PROGRESS : pageState[p.position];
const state = p.review ? submittedNavState : stateOfPage;
const state = p.review ? status : stateOfPage;
return {
label: p.label,
onNavigation: () => onSaveForm(false, p.position),
Expand All @@ -129,9 +130,10 @@ function Navigator({
hookForm,
allComplete,
formData,
submitted,
onFormSubmit,
additionalData,
onReview,
approvingManager,
reportId,
)}
{!page.review
Expand All @@ -158,8 +160,10 @@ function Navigator({
Navigator.propTypes = {
initialData: PropTypes.shape({}),
onFormSubmit: PropTypes.func.isRequired,
submitted: PropTypes.bool.isRequired,
onSave: PropTypes.func.isRequired,
status: PropTypes.string.isRequired,
onReview: PropTypes.func.isRequired,
approvingManager: PropTypes.bool.isRequired,
pages: PropTypes.arrayOf(
PropTypes.shape({
review: PropTypes.bool.isRequired,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/fetchers/Admin.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import join from 'url-join';
import { get, put } from './index';
import { DECIMAL_BASE } from '../Constants';

export const getUsers = async () => {
const users = await get((join('/', 'api', 'admin', 'users')));
return users.json();
};

export const updateUser = async (userId, data) => {
const user = await put((join('/', 'api', 'admin', 'users', userId.toString(10))), data);
const user = await put((join('/', 'api', 'admin', 'users', userId.toString(DECIMAL_BASE))), data);
return user.json();
};
13 changes: 10 additions & 3 deletions frontend/src/fetchers/activityReports.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import join from 'url-join';
import { get, put, post } from './index';
import { DECIMAL_BASE } from '../Constants';

const activityReportUrl = join('/', 'api', 'activity-reports');

Expand All @@ -9,13 +10,13 @@ export const getApprovers = async (region) => {
};

export const submitReport = async (reportId, data) => {
const url = join(activityReportUrl, reportId.toString(10), 'submit');
const url = join(activityReportUrl, reportId.toString(DECIMAL_BASE), 'submit');
const report = await post(url, data);
return report.json();
};

export const saveReport = async (reportId, data) => {
const report = await put(join(activityReportUrl, reportId.toString(10)), data);
const report = await put(join(activityReportUrl, reportId.toString(DECIMAL_BASE)), data);
return report.json();
};

Expand All @@ -25,7 +26,7 @@ export const createReport = async (data) => {
};

export const getReport = async (reportId) => {
const report = await get(join(activityReportUrl, reportId.toString(10)));
const report = await get(join(activityReportUrl, reportId.toString(DECIMAL_BASE)));
return report.json();
};

Expand All @@ -39,3 +40,9 @@ export const getCollaborators = async (region) => {
const collaborators = await get(url);
return collaborators.json();
};

export const reviewReport = async (reportId, data) => {
const url = join(activityReportUrl, reportId.toString(DECIMAL_BASE), 'review');
const report = await put(url, data);
return report.json();
};
64 changes: 64 additions & 0 deletions frontend/src/pages/ActivityReport/Pages/ApproverReviewPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Dropdown, Form, Label, Fieldset, Textarea, Alert, Button,
} from '@trussworks/react-uswds';

const possibleStatus = [
'Approved',
'Needs Action',
];

const ApproverReviewPage = ({
reviewed,
additionalNotes,
register,
valid,
handleSubmit,
onFormReview,
}) => (
<>
{reviewed
&& (
<Alert noIcon className="margin-y-4" type="success">
<b>Success</b>
<br />
Your review of this report was successfully submitted
</Alert>
)}
<h2>Review and approve report</h2>
<div className="smart-hub--creator-notes">
<p>
<span className="text-bold">Creator notes</span>
<br />
<br />
{ additionalNotes || 'No creator notes' }
</p>
</div>
<Form className="smart-hub--form-large" onSubmit={handleSubmit(onFormReview)}>
<Fieldset className="smart-hub--report-legend smart-hub--form-section" legend="Review and submit report">
<Label htmlFor="managerNotes">Manager notes</Label>
<Textarea inputRef={register} id="managerNotes" name="managerNotes" />
</Fieldset>
<Label htmlFor="status">Choose report status</Label>
<Dropdown id="status" name="status" defaultValue="" inputRef={register({ required: true })}>
<option name="default" value="" disabled hidden>- Select -</option>
{possibleStatus.map((status) => (
<option key={status} value={status}>{status}</option>
))}
</Dropdown>
<Button type="submit" disabled={!valid}>Submit</Button>
</Form>
</>
);

ApproverReviewPage.propTypes = {
reviewed: PropTypes.bool.isRequired,
additionalNotes: PropTypes.string.isRequired,
register: PropTypes.func.isRequired,
valid: PropTypes.bool.isRequired,
handleSubmit: PropTypes.func.isRequired,
onFormReview: PropTypes.func.isRequired,
};

export default ApproverReviewPage;
8 changes: 8 additions & 0 deletions frontend/src/pages/ActivityReport/Pages/ReviewSubmit.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.smart-hub--creator-notes {
padding: 1rem;
background-color: #f8f8f8;
}

#status {
max-width: 270px;
}
Loading

0 comments on commit d31f14f

Please sign in to comment.