Skip to content

Commit

Permalink
Merge branch 'main' into js-396-add-activity-reports-to-tta-history
Browse files Browse the repository at this point in the history
Conflicts:
	frontend/src/pages/GranteeRecord/index.js
	frontend/src/pages/GranteeRecord/pages/TTAHistory.js
  • Loading branch information
jasalisbury committed Nov 9, 2021
2 parents a578e94 + f9d28ac commit 8c8cf12
Show file tree
Hide file tree
Showing 27 changed files with 3,645 additions and 122 deletions.
7 changes: 5 additions & 2 deletions docs/boundary_diagram.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
System Boundary Diagram
=======================

![rendered boundary diagram](http://www.plantuml.com/plantuml/png/dLPHRnit37xFh-3oKAH04sDfNpOCGvtOJJCagvjpsvS2WQoZRIqwIHKfkyRG_pvHELzySJCKVKYiayIF7qNoaruJgyYfiGU_6ATjgX6Mp85-7moYMfyi32_JB156xHsZunFjcu6ger5kPLD8W_DNnnEh77-ulXfOnKYSfsxFlMDb7CQJ8DXis29CfqEe6XKPtgOPp7nojOeRM1bS7qmmadT7eVmuj2_Wy67h1y9uc6U63j3Lnq87_1nu-GZpyFaMfyOLMf_HUZYZxUnXRtgLGNs4peP0kHekfjSPxwnbUQJM90m-LN3XL-VMf_hmEVnx0D3jq3AvyAkyhGnFyhZT0r1jYB6v7NzbGRfLThQx3QnNzV5CMULqOLSS3Q_ECeE-TUVbLWNJWnXEBlzdT_I9osdyySog3KRw4nvCxnT9_9R8u8t453V0KStdHWDXN1cDBVx3cR2V2LUj8zQ65HllkjKkT82k6exMwtKc7dey-cNn2MSm3C4QNU24qz--nh-g5p3-6Y9IJiCDAisoCZ8KCinzmhIt5ZLJ0QmLgnEuJfPDi0Z64SlP4iJad76B7CeUDn_lCBRq7f4gIq_nEalMolS4uzp71cPAtosY70C8PY4dV214hv7e--wrLOsIudbZB09fLNYMj9Qyg6RuKKQNZZ4wPK4zi87izy6az4SAKbEqxsWqArcePyBO4oyYLk-lOAHOpHJXjlXkHfKCMpE2jl_RatPpiqYnyztFuPC-wMKBNhs4MT9to8VTH6b9zX49I2f9mrpEGH4XFns5r9tqvOtyxiKmjeeoajBBClK-OKBmyzq4_UDd1Epl4-LTw-ZRWVnzExZlfAEtrRZAzl9JQ1gti0YLMJXuvpwxwpT3M1a5KzFWyPaYhALIm4UON7u4hMBzEU-gV8gwkB-8oZ5YeRihCGjIjwGKIGrWVJEydXoh4A9VPS1AgQfqLA-z7QuZMgEb674DDpBUPisuv1F1jNU6VImrboFAMtR5SGVWMZcrG0ZtHIpD0i_0-iKYcmfckHRWOZmTJDvL-T-7wM0qlXfFnt3qwjNBvnbTiDi6xo5733uo0QF51Zbk18vrw1dkAF-3G3Q5KzVGFqR3UKQ8Ph5ay0wiSNS7Gsj12xgMYYMeCHZDM8EA2EXqt0JvMXjUmlIgWbzFJY4vYqJWUObnRGX1SEkJ0tHr6GhhhgftxwtQhvtqNbl0p4el6tHCFVgzuBk8z_KwHF_LY6xXbuJ4zEEfsCFgSlFpe3sHx1HBb8TAk3j8WW97lprXsxPKH8u6LzZrn5wQzwjhnrmbNgAJ5cUaedjY-swOfq_twwerMc4qymsOMYnvinzxv_BCz9nsiXbHrJHOHoDUXJ4XGqJjOqq25-YBxSoxg7yMeKz0gctVV2lFOhiA6j3LmHl7-on-5cQFo5PwqNqHNIMHKWWggWQtZucovIaA7K2DtmM0Pv129jLU2Ac7s6bcgsNINrljFBySd8zWOW9Qut1VDCkRLf9mOLXkAr7sjzMnX1wzjIZtMuqWgaM6lRna-W3QH6rH6_5LXkUNZqHNxkX5UprMtTjfJtqx9fCqiuQMnR50vGMW_7rqUjgMViTwrxbl6iEmzFvE5CdCfQMtZ80znEJW_ZH2Tne5x07aqNDoXC7wJUzfuHrGqXg9vicsS1au8rsfpUteaN3VpzwqLsQPU8skJetz3m00)
![rendered boundary diagram](http://www.plantuml.com/plantuml/svg/dLP1Rnkz4RtxLqnz26JWiuKwkRGeYiYMuhYm6yMh99S01iKThLXpoGrdA4Kjyj_BeLPhhHH_27AmnIKvRzvmPXxvbbW5ZhKz-OjnsiOIOSdSqD-7mw3M5vNXPPn7mg2zOtHyeNqzL6KmogriREBm-itvr2h7d-xlXbOn4gUfnsllM1c7uQ8HR3Pi4MQp4HIr2WplunpcFhfIXGsi3AvFfXZ8kq6JVnpQF-3qUUidmd2QPaOEq9NdGWVy0dXvW7bwjiCfSONM9xGUpdWtUzgRNYLG7w2p8L2kX9lPVSAxQbaEr9g4mPS2RlpgslfOdfx1_qwWYtI0jJBsaJ2iijjHhVxh7HIcRYp2H1QXo8imA2R5cN2OBOEFrH9c8HB9X8GZbFBkBLGY0T3HqEAvygkqDmylqdXB102A3J7MZvFlB7GVbPtlRmFhLNa-LrOvdM3RQ4PtL-AXPzrvULIDwK6CfhT_iZluo3dsVxooQeE1_WdFfjl576K-FdWdCOKDS52BXT4vNAEnnNy-UFPpuQfrmDAmOkDTjzg53dk9MA_NYNZJuz6llIyuXr7JMACpd73wjo_nNyKVCFdU1AIKwmTKccLbRAX9CDkgqDvQr4mPi5IiBk0-MZQIO-E8vMm9GdJEk4f2EUJcmnE6bju1gRpq4g-hQAryJp4iVAXXhlHJ5UGOG325NEO3JV0QYNxkNbjLAocUTyOYa5QPPqvhpekgHvzbTEiOWrCMr3CRI7wVJN8JnaPgYeuTZUSv2-LS67lYAc3nyGx6YjLS4UwAxs5SoB0r8sX5fZrfjp1L39tlVWvVz4clM_3YDSoZVa8-xIPotxCFI41IIHeMSWwA2FdbAAJkfFaVvFSeXebLb92KNkQfZn4ZWb_i9-W_Vax0Vfiexrf7FqxaxyV9jfC6xvCe97lvoJIDgon2OIe77znNT_zk12kZO6PgFBzIXALK2lW0qzlFe5KelwPTXOz1P_StGJb6p7JtTQmYzKXAaTG0bW-Z--cvQfhWLmcmKAh87TLhRuVhWDPeAKPSmuECTrapBlf8SE-TOHzopQM8qfPz1Tu3k5TELGZDjeYbMU0LM5zLoLGmyzq3DvFPSFgXIFy-pORZoTraDe71cpUlpnAwOBSDtaCEsFZ018mMQ-Im4JZMJSzmxtfv5iWwS-eQ-jTeECy8mLHB1k_06lTqCh8MjA1hgLY24XkZ6KjG0G6T3fj6ljQ6a-3V5V3NYqk8pY8HU5vYM1j24DpouWHTcOV2kglg_Sknz6idlTSMCBFIoneTKuz-B_WkucEzReB_RaIty5j4OlhrL1nXTRdvVT2UI7QA9Sf3ETmz9461mTzUi6rRAY07WoliUk8epOVLrJDNaPVefCKPAUkUs7uOfUdBmxhgZ5OOp683fXHBtXp7thcyCZsddMm6L2KDry68Ls5Co11G-r2Im3NqpNRcNTI_Yz0d8DLsRBwJPx5TDHhGbOqtZWzP_3xC8P5EUj5z4rqbaL9eL50rxXuJUSi1XME04dyA0AyWDebKUo747cAdcQsMIN_jjFFwTdWzXgbfq1g7nwAP7ywIX1l3Sbk9ihylpYNquAr5kTzA154jCkpb9TC7q2PeYzg8hpoylZqGNRcZg_PwBBgtqv7wTaocSMuDBRDZWKeBGEbxS7dPbdx7Uj-vhsl3iFJ-IHJ9BAIbTuo0FOJeO7iQJNSQ6UmPvE0vESR6-atlQU4TKDGQYHRHRk44-B0a3fxO1Rgo1vC9jX_K6lTjkaxz5VCxjNaS7rmQszc7V5st4syJJgpj_m40)

UML Source
----------
Expand All @@ -26,6 +26,7 @@ Boundary(aws, "AWS GovCloud") {
ContainerDb(www_redis, "Redis Database", "AWS Elasticache", "Queue of background jobs to work on")
}
}
Container(email_server, "Amazon Simple Email Server (SES)", "Through Truss", "TTA Hub mail server")
}
System(HSES, "HSES", "Single Sign On\nMFA via Time-Based App or PIV card\n\nSource of Grantee Data")
Boundary(gsa_saas, "FedRAMP-approved SaaS") {
Expand Down Expand Up @@ -57,6 +58,8 @@ Boundary(development_saas, "CI/CD Pipeline") {
Rel(developer, github, "Publish code", "git ssh (22)")
Rel(github, circleci, "Commit hook notifies CircleCI to run CI/CD pipeline")
Rel(circleci, cloudgov_api, "Deploy application on successful CI/CD run")
Rel(www_app, email_server, "Send application notifications")
Rel(email_server, personnel, "Send application notifications")
Lay_D(personnel, aws)
Lay_R(HSES, aws)
@enduml
Expand All @@ -65,7 +68,7 @@ Lay_R(HSES, aws)
Instructions
------------

1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/uml/dLPHRnit37xFh-3oKAH04sDfNpOCGvtOJJCagvjpsvS2WQoZRIqwIHKfkyRG_pvHELzySJCKVKYiayIF7qNoaruJgyYfiGU_6ATjgX6Mp85-7moYMfyi32_JB156xHsZunFjcu6ger5kPLD8W_DNnnEh77-ulXfOnKYSfsxFlMDb7CQJ8DXis29CfqEe6XKPtgOPp7nojOeRM1bS7qmmadT7eVmuj2_Wy67h1y9uc6U63j3Lnq87_1nu-GZpyFaMfyOLMf_HUZYZxUnXRtgLGNs4peP0kHekfjSPxwnbUQJM90m-LN3XL-VMf_hmEVnx0D3jq3AvyAkyhGnFyhZT0r1jYB6v7NzbGRfLThQx3QnNzV5CMULqOLSS3Q_ECeE-TUVbLWNJWnXEBlzdT_I9osdyySog3KRw4nvCxnT9_9R8u8t453V0KStdHWDXN1cDBVx3cR2V2LUj8zQ65HllkjKkT82k6exMwtKc7dey-cNn2MSm3C4QNU24qz--nh-g5p3-6Y9IJiCDAisoCZ8KCinzmhIt5ZLJ0QmLgnEuJfPDi0Z64SlP4iJad76B7CeUDn_lCBRq7f4gIq_nEalMolS4uzp71cPAtosY70C8PY4dV214hv7e--wrLOsIudbZB09fLNYMj9Qyg6RuKKQNZZ4wPK4zi87izy6az4SAKbEqxsWqArcePyBO4oyYLk-lOAHOpHJXjlXkHfKCMpE2jl_RatPpiqYnyztFuPC-wMKBNhs4MT9to8VTH6b9zX49I2f9mrpEGH4XFns5r9tqvOtyxiKmjeeoajBBClK-OKBmyzq4_UDd1Epl4-LTw-ZRWVnzExZlfAEtrRZAzl9JQ1gti0YLMJXuvpwxwpT3M1a5KzFWyPaYhALIm4UON7u4hMBzEU-gV8gwkB-8oZ5YeRihCGjIjwGKIGrWVJEydXoh4A9VPS1AgQfqLA-z7QuZMgEb674DDpBUPisuv1F1jNU6VImrboFAMtR5SGVWMZcrG0ZtHIpD0i_0-iKYcmfckHRWOZmTJDvL-T-7wM0qlXfFnt3qwjNBvnbTiDi6xo5733uo0QF51Zbk18vrw1dkAF-3G3Q5KzVGFqR3UKQ8Ph5ay0wiSNS7Gsj12xgMYYMeCHZDM8EA2EXqt0JvMXjUmlIgWbzFJY4vYqJWUObnRGX1SEkJ0tHr6GhhhgftxwtQhvtqNbl0p4el6tHCFVgzuBk8z_KwHF_LY6xXbuJ4zEEfsCFgSlFpe3sHx1HBb8TAk3j8WW97lprXsxPKH8u6LzZrn5wQzwjhnrmbNgAJ5cUaedjY-swOfq_twwerMc4qymsOMYnvinzxv_BCz9nsiXbHrJHOHoDUXJ4XGqJjOqq25-YBxSoxg7yMeKz0gctVV2lFOhiA6j3LmHl7-on-5cQFo5PwqNqHNIMHKWWggWQtZucovIaA7K2DtmM0Pv129jLU2Ac7s6bcgsNINrljFBySd8zWOW9Qut1VDCkRLf9mOLXkAr7sjzMnX1wzjIZtMuqWgaM6lRna-W3QH6rH6_5LXkUNZqHNxkX5UprMtTjfJtqx9fCqiuQMnR50vGMW_7rqUjgMViTwrxbl6iEmzFvE5CdCfQMtZ80znEJW_ZH2Tne5x07aqNDoXC7wJUzfuHrGqXg9vicsS1au8rsfpUteaN3VpzwqLsQPU8skJetz3m00)
1. [Edit this diagram with plantuml.com](http://www.plantuml.com/plantuml/umla/dLRVRnk_3N_FNy7beN20Rs8ixSk6OQWJksc6P7LpRljI891rz5cBJhgAb5rlwFy-KJvVV7RpHL6WZNKI-U67uW_gBR4A76jxyXVZj8qbmfAveRyFXq6jBoh3opYFX45xn-ZuGljwgCfWb5lPsCJXzPlpgLMEFztV3QrY94vRZzT9MXc7uQ8HR3Pi4MQp4HIr2WplunpcFhfIXGsi3AvFfXZ8kq6JVnpQF-3qMVGJOJXDEoC7wCfpeGD-0Rmym3mzs-6Kk4Bh4reFPxpRFUrjhnAe3z3f42XNmitiFk5TjIm7Qat2u4i1DtvrRNqiJy_WVoS0dOIMpSglabXUNgHrAmDGR8YnVfnyPq5wL7Q-BmRMg_9yhgnoEhFBXaPtLub1NxkpygWQquCOJM__H3huoFas_l7AgWq6-YSygsuFIUncp-2T-1Gsm44j5aO3OLWPZIt-yvsmdmjNhGEMXXKRxxhJpdM0BXi6w_Kw4MzwFFffyGNdC6eQQtI64qx_zYN-g_W39j-RW9J2y81AivoC3JK9PXimxQr5pPG1IyNg0kwZPTDO1EE8vMu9GdJEk4fSEUJcmnE6bju1gNpq4g-hQAryJp4iVAXXhlHJ5UGQG30pEU43JV0QYNvkNbjLAqcUTyOYa5QPPmvhZekgHvzbTUiOWrCMr3CRI7QVLN9zn4PoYeuDZUSv2kLS67lYAc3nyGx6YjLS4UwIxs5SoB9L8sZhlxrfjp1L39tjVWnVj4clM_3YDSoZVa8-xJPoIR8FI42IIHeMSW-A2FbbBoJlf2uVvFV8XubLb92KNkQjZn4ZWb_i1-W_Vax0VXiexrf3Fqxa_rvmi5R6FaePO13mMltNEoXCBSaraKCeyY4CYabn9jPcosIXMi8iHABJDgKacRBq5YgP-t6oBTV1-wIOfEGdtuLnbSLaedBmmNrrz-z6i38APgR6yoj5M4ewWWymlVqCMeNoQv8gV0mw-tWJb6F4V2VxVQmYzKXAaIGQbW-Z--cvQfhWLmcmKAh8PTlh8GxN0QtHal6uXWTPxrB3kEWZmRrtXdr8bBD7IMI_0-y1t2kdAeHcMobIaV0AhA-gf2gOUVR0pMGsd7ueqfzFi-5uSZUPJM3mvithiuGks6qNwI47R7nW0aQBDNBO21phfgUuDrwUkt2TENLTuzTeECy8mLHB1k_06lTqCh8MjA1hAGk24XkZ6KjG0G6T3fj6ljQ6KrBS5V3NYqk8pY8HU5vYM1j24DpouWHTcPV2kYkT_U5O-hMJ0c-hX3abUOsEgKU_vtpdyV5GQ8B_RgGvuhU8nFJheJZ2wcBp-w2zJjorHMblbDtTGn8K6Fpj1Tssf09oCBZ2hYQEmdoONJrr5Nc9Jle88q5ito8VHcdxyZYlMgKL1hFOW2b5apV7ldSchqpFQDUR0wgIXkjWnAem9cG8g7qeIU0Q-cOxzSxhtqNe4v1iErRVpG3HNJKQq9MDDuwFMVmkp26Hhh-ZIpaKaQHVGwE2gd7tOiaYXnIE04hyAG2yWjWaKktKYJt4hcUslKpgQzSxhs-7rsEOcWQjSNZSDBSFvoHuOrX6edJszyMvk1wyjIX3j4IGhaM6lJoN-W3Q16rH6x6LbzUt1qrN7W9LEuEBxe5sr7qx9jCujuQMsR10fGEWz3sul6nJlsEzRzpNjM5OUlya7SaifAHtZ80zXEXWUnjDTniPx1dauCqwniRwJU_zalvHr1g95j6sS0duC2KEnd21hkp1P8Bj1xNAVPskKdz5_Kvj7iS7GsEx-z2EwxpnDk74sluV)
1. Copy and paste the final UML into the UML Source section
1. Update the img src and edit link target to the current values

Expand Down
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"lodash": "^4.17.20",
"moment": "^2.29.1",
"moment-timezone": "^0.5.33",
"plotly.js": "^2.5.1",
"plotly.js-basic-dist": "^2.2.1",
"prop-types": "^15.7.2",
"query-string": "^7.0.0",
Expand All @@ -34,6 +35,7 @@
"react-idle-timer": "^4.4.2",
"react-input-autosize": "^3.0.0",
"react-js-pagination": "^3.0.3",
"react-plotly.js": "^2.5.1",
"react-responsive": "^8.1.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/ActivityReportsTable/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.usa-table-container--scrollable {
margin-top: 0px;
}
2 changes: 2 additions & 0 deletions frontend/src/components/ActivityReportsTable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import ReportMenu from '../../pages/Landing/ReportMenu';
import ReportRow from './ReportRow';
import { REPORTS_PER_PAGE } from '../../Constants';

import './index.css';

const emptyReport = {
id: 0,
displayId: '',
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/ButtonSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function ButtonSelect(props) {
endDatePickerId,
dateRange,
disabled,
className,
} = props;

const [checked, setChecked] = useState(applied);
Expand Down Expand Up @@ -160,7 +161,7 @@ function ButtonSelect(props) {
const ariaLabel = `${menuIsOpen ? 'press escape to close ' : 'Open '} ${ariaName}`;

return (
<div className="margin-left-1" onBlur={onBlur} data-testid="data-sort">
<div className={className} onBlur={onBlur} data-testid="data-sort">
<button
onClick={setMenuIsOpen}
onKeyDown={onKeyDown}
Expand Down Expand Up @@ -301,6 +302,7 @@ ButtonSelect.propTypes = {
applied: PropTypes.number.isRequired,
ariaName: PropTypes.string.isRequired,
disabled: PropTypes.bool,
className: PropTypes.string,

// style as a select box
styleAsSelect: PropTypes.bool,
Expand All @@ -321,6 +323,7 @@ ButtonSelect.defaultProps = {
startDatePickerId: '',
endDatePickerId: '',
disabled: false,
className: 'margin-left-1',
};

export default ButtonSelect;
4 changes: 3 additions & 1 deletion frontend/src/pages/ActivityReport/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Note that if this topic list is changed, it needs also to be changed in
// - src/constants.js
export const reasons = [
'Below Competitive Threshold (CLASS)',
'Below Quality Threshold (CLASS)',
Expand Down Expand Up @@ -69,7 +71,7 @@ export const programTypes = [
];

// Note that if this topic list is changed, it needs also to be changed in
// - src/widgets/topicFrequencyGraph.js
// - src/constants.js
export const topics = [
'Behavioral / Mental Health / Trauma',
'Child Assessment, Development, Screening',
Expand Down
27 changes: 6 additions & 21 deletions frontend/src/pages/GranteeRecord/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export default function GranteeRecord({ match, location }) {
'grants.number': '',
granteeId,
});
const [filters, setFilters] = useState([

const defaultFilters = [
{
id: uuidv4(),
topic: 'region',
Expand All @@ -36,29 +37,13 @@ export default function GranteeRecord({ match, location }) {
condition: 'Contains',
query: granteeId,
},
]);
];

// set filters will be used very soon, disabling warning
// eslint-disable-next-line no-unused-vars
const [filters, setFilters] = useState(defaultFilters);
const [error, setError] = useState();

useEffect(() => {
const filtersToApply = [
{
id: uuidv4(),
topic: 'region',
condition: 'Contains',
query: regionId,
},
{
id: uuidv4(),
topic: 'granteeId',
condition: 'Contains',
query: granteeId,
},
];

setFilters(filtersToApply);
}, [granteeId, regionId]);

useEffect(() => {
async function fetchGrantee(id, region) {
try {
Expand Down
41 changes: 25 additions & 16 deletions frontend/src/pages/GranteeRecord/pages/TTAHistory.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Grid } from '@trussworks/react-uswds';
import Overview from '../../../widgets/DashboardOverview';
import ActivityReportsTable from '../../../components/ActivityReportsTable';
import FrequencyGraph from '../../../widgets/FrequencyGraph';

export default function TTAHistory({ filters }) {
return (
<div className="margin-right-3">
<Overview
fields={[
'Activity reports',
'Hours of TTA',
'Participants',
'In-person activities',
]}
showTooltips
filters={filters}
/>
<ActivityReportsTable
filters={filters}
showFilter={false}
onUpdateFilters={() => {}}
tableCaption="Activity Reports"
/>
<Grid>
<Grid col={12}>
<Overview
fields={[
'Activity reports',
'Hours of TTA',
'Participants',
'In-person activities',
]}
showTooltips
filters={filters}
/>
</Grid>
<Grid desktop={{ col: 8 }} tablet={{ col: 12 }}>
<FrequencyGraph filters={filters} />
</Grid>
<ActivityReportsTable
filters={filters}
showFilter={false}
onUpdateFilters={() => {}}
tableCaption="Activity Reports"
/>
</Grid>
</div>
);
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import 'react-dates/initialize';
// 'MutationObserver shim removed'
import MutationObserver from '@sheerun/mutationobserver-shim';

// See https://github.com/plotly/react-plotly.js/issues/115
window.URL.createObjectURL = () => {};

window.MutationObserver = MutationObserver;
jest.setTimeout(50000);

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/widgets/BarGraph.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.smart-hub--vertical-text {
writing-mode: vertical-lr;
transform: rotate(180deg);
}
138 changes: 138 additions & 0 deletions frontend/src/widgets/BarGraph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import Plot from 'react-plotly.js';
import './BarGraph.css';

const WIDGET_PER_CATEGORY = 180;

/**
*
* Takes a string, a reason (or topic, if you prefer)
* provided for an activity report and intersperses it with line breaks
* depending on the length
*
* @param {string} topic
* @returns string with line breaks
*/
function topicsWithLineBreaks(reason) {
const arrayOfTopics = reason.split(' ');

return arrayOfTopics.reduce((accumulator, currentValue) => {
const lineBreaks = accumulator.match(/<br>/g);
const allowedLength = lineBreaks ? lineBreaks.length * 6 : 6;

// we don't want slashes on their own lines
if (currentValue === '/' || currentValue === '|' || currentValue === '&') {
return `${accumulator} ${currentValue}`;
}

if (accumulator.length > allowedLength) {
return `${accumulator}<br>${currentValue}`;
}

return `${accumulator} ${currentValue}`;
}, '');
}

function BarGraph({ data, yAxisLabel, xAxisLabel }) {
const [plot, updatePlot] = useState({});

useEffect(() => {
if (!data || !Array.isArray(data)) {
return;
}

const categories = [];
const counts = [];

data.forEach((dataPoint) => {
categories.push(dataPoint.category);
counts.push(dataPoint.count);
});

const trace = {
type: 'bar',
x: categories.map((category) => topicsWithLineBreaks(category)),
y: counts,
hoverinfo: 'y',
};

const width = categories.length * WIDGET_PER_CATEGORY;

const layout = {
bargap: 0.5,
height: 300,
hoverlabel: {
bgcolor: '#000',
bordercolor: '#000',
font: {
color: '#fff',
size: 16,
},
},
width,
margin: {
l: 80,
pad: 20,
t: 24,
},
xaxis: {
automargin: true,
fixedrange: true,
tickangle: 0,
},
yaxis: {
tickformat: ',.0d',
fixedrange: true,
},
hovermode: 'none',
};

updatePlot({
data: [trace],
layout,
config: {
responsive: true, displayModeBar: false, hovermode: 'none',
},
});
}, [data]);

return (
<>
<div className="display-flex flex-align-center">
<div className="margin-right-1 smart-hub--vertical-text">
{ yAxisLabel }
</div>
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */}
<div className="overflow-x-scroll" tabIndex={0}>
<caption className="sr-only">Use the arrow keys to scroll graph</caption>
<Plot
data={plot.data}
layout={plot.layout}
config={plot.config}
/>
</div>
</div>
<div className="display-flex flex-justify-center margin-top-1">
{ xAxisLabel }
</div>
</>
);
}

BarGraph.propTypes = {
data: PropTypes.arrayOf(
PropTypes.shape({
category: PropTypes.string,
count: PropTypes.number,
}),
),
yAxisLabel: PropTypes.string.isRequired,
xAxisLabel: PropTypes.string.isRequired,
};

BarGraph.defaultProps = {
data: [],
};

export default BarGraph;
10 changes: 5 additions & 5 deletions frontend/src/widgets/DashboardOverview.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,23 @@ Field.defaultProps = {
const DASHBOARD_FIELDS = [
{
key: 'Activity reports',
render: (data, showTooltip) => <Field showTooltip={showTooltip} tooltipText="The total number of approved activity reports." icon={faChartBar} iconColor="#148439" backgroundColor="#F0FCF4" label="Activity reports" data={data.numReports} />,
render: (data, showTooltip) => <Field key="activity-reports" showTooltip={showTooltip} tooltipText="The total number of approved activity reports." icon={faChartBar} iconColor="#148439" backgroundColor="#F0FCF4" label="Activity reports" data={data.numReports} />,
},
{
key: 'Grants served',
render: (data) => <Field showTooltip={false} icon={faBuilding} iconColor="#2B7FB9" backgroundColor="#E2EFF7" label="Grants served" data={data.numGrants} />,
render: (data) => <Field key="grants-served" showTooltip={false} icon={faBuilding} iconColor="#2B7FB9" backgroundColor="#E2EFF7" label="Grants served" data={data.numGrants} />,
},
{
key: 'Participants',
render: (data, showTooltip) => <Field showTooltip={showTooltip} tooltipText="The total number of people involved in all activities." icon={faUserFriends} iconColor="#264A64" backgroundColor="#ECEEF1" label="Participants" data={data.numParticipants} />,
render: (data, showTooltip) => <Field key="participants" showTooltip={showTooltip} tooltipText="The total number of people involved in all activities." icon={faUserFriends} iconColor="#264A64" backgroundColor="#ECEEF1" label="Participants" data={data.numParticipants} />,
},
{
key: 'Hours of TTA',
render: (data, showTooltip) => <Field showTooltip={showTooltip} tooltipText="The total number of hours spent on all TTA activities." icon={faClock} iconColor="#E29F4D" backgroundColor="#FFF1E0" label="Hours of TTA" data={data.sumDuration} decimalPlaces={1} />,
render: (data, showTooltip) => <Field key="hours-of-tta" showTooltip={showTooltip} tooltipText="The total number of hours spent on all TTA activities." icon={faClock} iconColor="#E29F4D" backgroundColor="#FFF1E0" label="Hours of TTA" data={data.sumDuration} decimalPlaces={1} />,
},
{
key: 'In-person activities',
render: (data, showTooltip) => <Field icon={faUser} showTooltip={showTooltip} tooltipText="Number of activities that were conducted in-person vs. virtual." iconColor="#A12854" backgroundColor="#FFE8F0" label="In-person activities" data={data.inPerson} />,
render: (data, showTooltip) => <Field key="in-person-activities" icon={faUser} showTooltip={showTooltip} tooltipText="Number of activities that were conducted in-person vs. virtual." iconColor="#A12854" backgroundColor="#FFE8F0" label="In-person activities" data={data.inPerson} />,
},
];

Expand Down
Loading

0 comments on commit 8c8cf12

Please sign in to comment.