-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement basic agency routing + view metric data viz w/ live data (#105
) * implement basic agency routing + view metric data viz w/ live data * move toast to common * add jest tests * fix importing png type
- Loading branch information
1 parent
5f5b20d
commit 7a1c92c
Showing
37 changed files
with
701 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
REACT_APP_PROXY_HOST=http://localhost:5001 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Recidiviz - a data platform for criminal justice reform | ||
// Copyright (C) 2022 Recidiviz, Inc. | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
// ============================================================================= | ||
|
||
import { palette } from "@justice-counts/common/components/GlobalStyles"; | ||
import styled from "styled-components/macro"; | ||
|
||
export const MetricCategory = styled.div` | ||
height: 100px; | ||
width: 100%; | ||
position: relative; | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
align-items: center; | ||
color: ${palette.solid.blue}; | ||
&:hover { | ||
cursor: pointer; | ||
text-decoration: underline; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Recidiviz - a data platform for criminal justice reform | ||
// Copyright (C) 2022 Recidiviz, Inc. | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
// ============================================================================= | ||
import { render, screen } from "@testing-library/react"; | ||
import React from "react"; | ||
import { MemoryRouter } from "react-router-dom"; | ||
|
||
import AgencyOverview from "./AgencyOverview"; | ||
import { StoreProvider } from "./stores"; | ||
|
||
beforeEach(() => { | ||
fetchMock.resetMocks(); | ||
}); | ||
|
||
// test("renders loading state", () => { | ||
// fetchMock.mockResponseOnce( | ||
// JSON.stringify({ | ||
// datapoints: [], | ||
// dimension_names_by_metric_and_disaggregation: {}, | ||
// }) | ||
// ); | ||
|
||
// render( | ||
// <StoreProvider> | ||
// <MemoryRouter initialEntries={["/agency/1"]}> | ||
// <AgencyOverview /> | ||
// </MemoryRouter> | ||
// </StoreProvider> | ||
// ); | ||
// const loadingElement = screen.getByText(/Loading.../i); | ||
// expect(loadingElement).toBeInTheDocument(); | ||
// }); | ||
|
||
test("renders 'No published metrics' state", async () => { | ||
fetchMock.mockResponseOnce( | ||
JSON.stringify({ | ||
datapoints: [], | ||
dimension_names_by_metric_and_disaggregation: {}, | ||
}) | ||
); | ||
|
||
render( | ||
<StoreProvider> | ||
<MemoryRouter initialEntries={["/agency/1"]}> | ||
<AgencyOverview /> | ||
</MemoryRouter> | ||
</StoreProvider> | ||
); | ||
|
||
const textElement = await screen.findByText(/No published metrics./i); | ||
expect(textElement).toBeInTheDocument(); | ||
}); | ||
|
||
test("renders list of metrics", async () => { | ||
fetchMock.mockResponseOnce( | ||
JSON.stringify({ | ||
datapoints: [{}], | ||
dimension_names_by_metric_and_disaggregation: { | ||
LAW_ENFORCEMENT_ARRESTS: {}, | ||
LAW_ENFORCEMENT_BUDGET: {}, | ||
LAW_ENFORCEMENT_CALLS_FOR_SERVICE: {}, | ||
}, | ||
}) | ||
); | ||
|
||
render( | ||
<StoreProvider> | ||
<MemoryRouter initialEntries={["/agency/1"]}> | ||
<AgencyOverview /> | ||
</MemoryRouter> | ||
</StoreProvider> | ||
); | ||
const textElement1 = await screen.findByText( | ||
/Click on a metric to view chart:/i | ||
); | ||
expect(textElement1).toBeInTheDocument(); | ||
const textElement2 = await screen.findByText(/LAW_ENFORCEMENT_ARRESTS/i); | ||
expect(textElement2).toBeInTheDocument(); | ||
const textElement3 = await screen.findByText(/LAW_ENFORCEMENT_BUDGET/i); | ||
expect(textElement3).toBeInTheDocument(); | ||
const textElement4 = await screen.findByText( | ||
/LAW_ENFORCEMENT_CALLS_FOR_SERVICE/i | ||
); | ||
expect(textElement4).toBeInTheDocument(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Recidiviz - a data platform for criminal justice reform | ||
// Copyright (C) 2022 Recidiviz, Inc. | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
// ============================================================================= | ||
|
||
import { showToast } from "@justice-counts/common/components/Toast"; | ||
import { observer } from "mobx-react-lite"; | ||
import React, { useEffect } from "react"; | ||
import { useNavigate, useParams } from "react-router-dom"; | ||
|
||
import { MetricCategory } from "./AgencyOverview.styles"; | ||
import { useStore } from "./stores"; | ||
|
||
const AgencyOverview = () => { | ||
const navigate = useNavigate(); | ||
const params = useParams(); | ||
const agencyId = Number(params.id); | ||
const { datapointsStore } = useStore(); | ||
|
||
const fetchDatapoints = async () => { | ||
try { | ||
await datapointsStore.getDatapoints(agencyId); | ||
} catch (error) { | ||
showToast("Error fetching data.", false, "red", 4000); | ||
} | ||
}; | ||
useEffect(() => { | ||
fetchDatapoints(); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
|
||
if (datapointsStore.loading) { | ||
return <>Loading...</>; | ||
} | ||
|
||
const metrics = Object.keys(datapointsStore.datapointsByMetric); | ||
if (metrics.length === 0) { | ||
return <>No published metrics.</>; | ||
} | ||
|
||
return ( | ||
<> | ||
Click on a metric to view chart: | ||
{Object.keys(datapointsStore.dimensionNamesByMetricAndDisaggregation).map( | ||
(metricKey) => ( | ||
<MetricCategory | ||
key={metricKey} | ||
onClick={() => { | ||
navigate(`/agency/${agencyId}/dashboard?metric=${metricKey}`); | ||
}} | ||
> | ||
{datapointsStore.metricKeyToDisplayName[metricKey] || metricKey} | ||
</MetricCategory> | ||
) | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default observer(AgencyOverview); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Recidiviz - a data platform for criminal justice reform | ||
// Copyright (C) 2022 Recidiviz, Inc. | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
// ============================================================================= | ||
import { render, screen } from "@testing-library/react"; | ||
import React from "react"; | ||
import { MemoryRouter } from "react-router-dom"; | ||
|
||
import DashboardView from "./DashboardView"; | ||
import { StoreProvider } from "./stores"; | ||
|
||
beforeEach(() => { | ||
fetchMock.resetMocks(); | ||
}); | ||
|
||
// test("renders loading state", () => { | ||
// fetchMock.mockResponseOnce( | ||
// JSON.stringify({ | ||
// datapoints: [{}], | ||
// dimension_names_by_metric_and_disaggregation: { | ||
// LAW_ENFORCEMENT_ARRESTS: {}, | ||
// LAW_ENFORCEMENT_BUDGET: {}, | ||
// LAW_ENFORCEMENT_CALLS_FOR_SERVICE: {}, | ||
// }, | ||
// }) | ||
// ); | ||
|
||
// render( | ||
// <StoreProvider> | ||
// <MemoryRouter | ||
// initialEntries={["/agency/1/dashboard?metric=LAW_ENFORCEMENT_ARRESTS"]} | ||
// > | ||
// <DashboardView /> | ||
// </MemoryRouter> | ||
// </StoreProvider> | ||
// ); | ||
// const loadingElement = screen.getByText(/Loading.../i); | ||
// expect(loadingElement).toBeInTheDocument(); | ||
// }); | ||
|
||
test("renders 'No reported data for this metric.' state", async () => { | ||
fetchMock.mockResponseOnce( | ||
JSON.stringify({ | ||
datapoints: [{}], | ||
dimension_names_by_metric_and_disaggregation: { | ||
LAW_ENFORCEMENT_ARRESTS: {}, | ||
LAW_ENFORCEMENT_BUDGET: {}, | ||
LAW_ENFORCEMENT_CALLS_FOR_SERVICE: {}, | ||
}, | ||
}) | ||
); | ||
|
||
render( | ||
<StoreProvider> | ||
<MemoryRouter | ||
initialEntries={["/agency/1/dashboard?metric=LAW_ENFORCEMENT_ARRESTS"]} | ||
> | ||
<DashboardView /> | ||
</MemoryRouter> | ||
</StoreProvider> | ||
); | ||
|
||
const textElement = await screen.findByText(/LAW_ENFORCEMENT_ARRESTS/i); | ||
expect(textElement).toBeInTheDocument(); | ||
}); |
Oops, something went wrong.