-
Notifications
You must be signed in to change notification settings - Fork 4
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
base: main
Are you sure you want to change the base?
Changes from all commits
6b4eb11
7f5206e
ab5f45a
fca8469
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
---|---|---|
|
@@ -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); | ||
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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`; | ||
|
@@ -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); | ||
|
@@ -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; | ||
|
||
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.