Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] VZV: Missing "Other" modes crashes on the map #1421

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion atd-vzv/src/views/map/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import MapPolygonFilter from "./MapPolygonFilter";
import MapCompassSpinner from "./MapCompassSpinner";
import { createMapDataUrl, useMapEventHandler } from "./helpers";
import { mapInit, travisCountyBboxGeoJSON, mapNavBbox } from "./mapData";
import { crashGeoJSONEndpointUrl } from "../../views/summary/queries/socrataQueries";
import {
crashGeoJSONEndpointUrl,
mapRequestFields,
} from "../../views/summary/queries/socrataQueries";
import {
baseSourceAndLayer,
fatalitiesDataLayer,
Expand Down Expand Up @@ -101,6 +104,7 @@ const Map = () => {
filters,
dateRange,
mapPolygon,
mapRequestFields,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a parameter to the helper that builds up the Socrata $select parameter so we can control what fields are returned when this function is reused. We were requesting unneeded geo fields here previously.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Mike. This is a great pattern that we'd do ourselves well adopting everywhere we can. That's a nice thing about graphql, you can't ask for *, you have to ask for columns by name.

mapTimeWindow
);

Expand Down
4 changes: 2 additions & 2 deletions atd-vzv/src/views/map/helpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useEffect } from "react";
import { mapRequestFields } from "../summary/queries/socrataQueries";
import { format } from "date-fns";

const convertDateToSocrataFormat = (date, suffix) =>
Expand Down Expand Up @@ -39,6 +38,7 @@ export const createMapDataUrl = (
filters,
dateRange,
mapPolygon,
fieldsToRequest,
mapTimeWindow = ""
) => {
const whereFilterString = generateWhereFilters(filters);
Expand All @@ -53,7 +53,7 @@ export const createMapDataUrl = (
// Return null to prevent populating map with unfiltered data
return filterCount === 0
? null
: `${endpoint}?$select=${mapRequestFields.join(",")}` +
: `${endpoint}?$select=${fieldsToRequest.join(",")}` +
`&$limit=100000` +
`&$where=crash_date between '${startDate}' and '${endDate}'` +
// if there is a polygon selected, add as filter
Expand Down
2 changes: 1 addition & 1 deletion atd-vzv/src/views/nav/SideMapControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ const SideMapControl = ({ type }) => {
</Row>
))}
<SideMapControlDateRange type={type} />
<SideMapTimeOfDayChart filters={mapOtherFilters.timeOfDay} />
<SideMapTimeOfDayChart timeWindowConfig={mapOtherFilters.timeOfDay} />
</Card>
<SideMapControlOverlays />
<SideMapFooter />
Expand Down
52 changes: 35 additions & 17 deletions atd-vzv/src/views/nav/SideMapTimeOfDayChart.js
Copy link
Contributor Author

@mddilley mddilley Apr 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this part is renaming variables and adding some comments to hopefully make it easier to read next time - open to changes here. The comment on the important change further down.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ import { Container, Button } from "reactstrap";
import { HorizontalBar } from "react-chartjs-2";
import { colors } from "../../constants/colors";

export const SideMapTimeOfDayChart = ({ filters }) => {
const fieldsToRequest = [
"death_cnt",
"sus_serious_injry_cnt",
"crash_id",
"crash_date",
];

export const SideMapTimeOfDayChart = ({ timeWindowConfig }) => {
const chartRef = useRef();

const defaultBarColor = colors.dark;
const inactiveBarColor = colors.white;

const [chartData, setChartData] = useState(null);
const [crashes, setCrashes] = useState(null);
const [timeWindowData, setTimeWindowData] = useState([]);
const [timeWindowPercentages, setTimeWindowPercentages] = useState([]);
const [barColors, setBarColors] = useState(defaultBarColor);
Expand All @@ -33,36 +40,47 @@ export const SideMapTimeOfDayChart = ({ filters }) => {
crashEndpointUrl,
mapFilters,
dateRange,
mapPolygon
mapPolygon,
fieldsToRequest
);

!!apiUrl &&
axios.get(apiUrl).then((res) => {
setChartData(res.data);
setCrashes(res.data);
});
}, [dateRange, mapPolygon, mapFilters]);

useMemo(() => {
const crashes = chartData;
// When chartData is set, accumulate time window data
if (!!crashes) {
const crashTimeWindowAccumulatorArray = Object.keys(filters).map(
(filter) => 0
// For each window of time in the config, add fatalities and serious injuries to initial count of 0
const crashTimeWindows = Object.values(timeWindowConfig).map(
(windowArray) => windowArray
);
const crashTimeWindowAccumulatorArray = Object.keys(timeWindowConfig).map(
() => 0
);
const crashTimeWindows = Object.values(filters).map((filter) => filter);

const crashTimeTotals = crashes.reduce((accumulator, crash) => {
crashTimeWindows.forEach((timeWindow, i) => {
const crashDate = crash.crash_date;
const crashHour = parseInt(format(new Date(crashDate), "H"));
crashHour >= timeWindow[0] &&
crashHour <= timeWindow[1] &&
accumulator[i]++;

const crashFatalities = parseInt(crash.death_cnt);
const seriousInjuries = parseInt(crash.sus_serious_injry_cnt);
const isCrashInTimeWindow =
crashHour >= timeWindow[0] && crashHour <= timeWindow[1];

if (isCrashInTimeWindow) {
accumulator[i] = accumulator[i] + crashFatalities + seriousInjuries;
}
Comment on lines +69 to +76
Copy link
Contributor Author

@mddilley mddilley Apr 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the fix. We used to add up the total number of crash records per time of day window that returned using the map filters for severity, mode, and date range.

Now, we add up the number of fatalities and serious injuries for each crash record.

});
return accumulator;
}, crashTimeWindowAccumulatorArray);

setTimeWindowData(crashTimeTotals);
}
}, [chartData, filters]);
}, [crashes, timeWindowConfig]);

useMemo(() => {
// When timeWindowData is set, calc percentages
Expand All @@ -86,12 +104,12 @@ export const SideMapTimeOfDayChart = ({ filters }) => {

const handleBarClick = (elems) => {
// Store bar label, if click is within a bar
const timeWindow = elems.length > 0 ? elems[0]._model.label : null;
const timeWindowLabel = elems.length > 0 ? elems[0]._model.label : null;
const index = elems.length > 0 ? elems[0]._index : null;

// If valid click, set mapTimeWindow state
if (!!timeWindow) {
const timeWindowArray = filters[timeWindow];
if (!!timeWindowLabel) {
const timeWindowArray = timeWindowConfig[timeWindowLabel];
const timeWindowStart = timeWindowArray[0];
const timeWindowEnd = timeWindowArray[1];
const timeWindowFilterString = ` AND date_extract_hh(crash_date) between ${timeWindowStart} and ${timeWindowEnd} AND date_extract_mm(crash_date) between 0 and 59`;
Expand All @@ -100,7 +118,7 @@ export const SideMapTimeOfDayChart = ({ filters }) => {

// Style unselected bars as inactive
if (index !== null) {
const newBarColors = Object.keys(filters).map((filter, i) =>
const newBarColors = Object.keys(timeWindowConfig).map((_, i) =>
i === index ? defaultBarColor : inactiveBarColor
);
setBarColors(newBarColors);
Expand All @@ -113,7 +131,7 @@ export const SideMapTimeOfDayChart = ({ filters }) => {
};

const createChartTimeLabels = () =>
Object.keys(filters).map((label) => label);
Object.keys(timeWindowConfig).map((label) => label);

const isMapTimeWindowSet = !!mapTimeWindow;

Expand Down