Skip to content

Commit

Permalink
Merge pull request #232 from caktus/develop
Browse files Browse the repository at this point in the history
Prepare production release v1.11.0 #227
  • Loading branch information
Afani97 authored Sep 19, 2023
2 parents e6fdb38 + 0ea9a73 commit 535fd18
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16-bullseye-slim as static_files
FROM node:18.17.0-bullseye-slim as static_files

WORKDIR /code
ENV PATH /code/node_modules/.bin:$PATH
Expand Down Expand Up @@ -148,7 +148,7 @@ RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/
&& curl https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor | tee /etc/apt/trusted.gpg.d/docker.gpg >/dev/null \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
# nodejs
&& sh -c 'echo "deb https://deb.nodesource.com/node_16.x $(lsb_release -cs) main" > /etc/apt/sources.list.d/nodesource.list' \
&& sh -c 'echo "deb https://deb.nodesource.com/node_18.x $(lsb_release -cs) main" > /etc/apt/sources.list.d/nodesource.list' \
&& wget --quiet -O- https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - \
# PostgreSQL
&& sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' \
Expand Down
17 changes: 11 additions & 6 deletions frontend/src/Components/Charts/TrafficStops/TrafficStops.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import TrafficStopsStyled, {
GroupedStopsContainer,
LineWrapper,
PieStopsContainer,
PieWrapper,
StopGroupsContainer,
SwitchContainer,
Expand Down Expand Up @@ -704,6 +705,7 @@ function TrafficStops(props) {
title="Stop Purposes By Group"
maintainAspectRatio={false}
displayStopPurposeTooltips
showLegendOnBottom={false}
/>
</StopGroupsContainer>
</LineWrapper>
Expand Down Expand Up @@ -763,6 +765,7 @@ function TrafficStops(props) {
maintainAspectRatio={false}
displayLegend={false}
yAxisMax={stopsGroupedByPurposeData.max_step_size}
redraw
/>
</GroupedStopsContainer>
<GroupedStopsContainer visible={visibleStopsGroupedByPurpose[1].visible}>
Expand All @@ -773,6 +776,7 @@ function TrafficStops(props) {
displayLegend={false}
yAxisMax={stopsGroupedByPurposeData.max_step_size}
yAxisShowLabels={!visibleStopsGroupedByPurpose[0].visible}
redraw
/>
</GroupedStopsContainer>
<GroupedStopsContainer visible={visibleStopsGroupedByPurpose[2].visible}>
Expand All @@ -785,6 +789,7 @@ function TrafficStops(props) {
yAxisShowLabels={
!visibleStopsGroupedByPurpose[0].visible && !visibleStopsGroupedByPurpose[1].visible
}
redraw
/>
</GroupedStopsContainer>
</LineWrapper>
Expand All @@ -797,30 +802,30 @@ function TrafficStops(props) {
/>
)}
<PieWrapper visible={checked === true}>
<GroupedStopsContainer visible={visibleStopsGroupedByPurpose[0].visible}>
<PieStopsContainer visible={visibleStopsGroupedByPurpose[0].visible}>
<PieChart
data={stopsGroupedByPurposePieData.safety}
title="Safety Violation"
maintainAspectRatio={false}
displayLegend={false}
/>
</GroupedStopsContainer>
<GroupedStopsContainer visible={visibleStopsGroupedByPurpose[1].visible}>
</PieStopsContainer>
<PieStopsContainer visible={visibleStopsGroupedByPurpose[1].visible}>
<PieChart
data={stopsGroupedByPurposePieData.regulatory}
title="Regulatory/Equipment"
maintainAspectRatio={false}
displayLegend={false}
/>
</GroupedStopsContainer>
<GroupedStopsContainer visible={visibleStopsGroupedByPurpose[2].visible}>
</PieStopsContainer>
<PieStopsContainer visible={visibleStopsGroupedByPurpose[2].visible}>
<PieChart
data={stopsGroupedByPurposePieData.other}
title="Other"
maintainAspectRatio={false}
displayLegend={false}
/>
</GroupedStopsContainer>
</PieStopsContainer>
</PieWrapper>

<Legend
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/Components/Charts/TrafficStops/TrafficStops.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ export const LineWrapper = styled.div`
export const PieWrapper = styled.div`
display: ${(props) => (props.visible ? 'flex' : 'none')};
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
justify-content: space-evenly;
@media (${smallerThanTabletLandscape}) {
flex-direction: column;
}
`;

export const StopGroupsContainer = styled.div`
Expand All @@ -31,7 +34,16 @@ export const StopGroupsContainer = styled.div`
`;

export const GroupedStopsContainer = styled.div`
width: 30%;
width: 80%;
height: 500px;
@media (${smallerThanTabletLandscape}) {
width: 100%;
}
display: ${(props) => (props.visible ? 'block' : 'none')};
`;

export const PieStopsContainer = styled.div`
width: 33%;
height: 500px;
@media (${smallerThanTabletLandscape}) {
width: 100%;
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/Components/Elements/Table/TableModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -531,17 +531,17 @@ function TableModal({ chartState, dataSet, columns, isOpen, closeModal }) {
const subheadingForDataset = (ds) => {
const message = 'The following data correspond to the number of times each race was';
if (ds === CONTRABAND_HIT_RATE) {
return `${message} found with contraband during a stop totalled by year.`;
return `${message} found with contraband during a stop totaled by year.`;
}
if (ds === LIKELIHOOD_OF_SEARCH) {
if (consolidateYears) {
return `${message} searched during a stop totalled by year.`;
return `${message} searched during a stop totaled by year.`;
}
return `${message} searched during a specific stop reason.`;
}
if (ds === STOPS_BY_REASON) {
if (consolidateYears) {
return `${message} stopped totalled by year.`;
return `${message} stopped totaled by year.`;
}
return `${message} stopped for a specific reason.`;
}
Expand Down
36 changes: 24 additions & 12 deletions frontend/src/Components/NewCharts/LineChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Line } from 'react-chartjs-2';
import { tooltipLanguage } from '../../util/tooltipLanguage';
import { usePopper } from 'react-popper';
import styled from 'styled-components';
import DataLoading from '../Charts/ChartPrimitives/DataLoading';

export const Tooltip = styled.div`
background: #333;
Expand All @@ -21,13 +22,14 @@ export const Tooltip = styled.div`
export default function LineChart({
data,
title,
maintainAspectRatio = true,
maintainAspectRatio = false,
displayTitle = true,
displayLegend = true,
yAxisMax = null,
yAxisShowLabels = true,
displayStopPurposeTooltips = false,
showLegendOnBottom = true,
redraw = false,
}) {
const options = {
responsive: true,
Expand All @@ -47,8 +49,10 @@ export default function LineChart({
}
},
onLeave() {
setTooltipText('');
hideTooltip();
if (displayStopPurposeTooltips) {
setTooltipText('');
hideTooltip();
}
},
},
tooltip: {
Expand Down Expand Up @@ -94,17 +98,25 @@ export default function LineChart({
popperElement.removeAttribute('data-show');
};

if (!data.datasets.length) {
return <DataLoading />;
}

return (
<>
<div ref={setReferenceElement} />
<Tooltip
ref={setPopperElement}
style={{ ...styles.popper, width: '300px' }}
{...attributes.popper}
>
{tooltipText}
</Tooltip>
<Line options={options} data={data} />
{displayStopPurposeTooltips && (
<>
<div ref={setReferenceElement} />
<Tooltip
ref={setPopperElement}
style={{ ...styles.popper, width: '300px' }}
{...attributes.popper}
>
{tooltipText}
</Tooltip>
</>
)}
<Line options={options} data={data} redraw={redraw} datasetIdKey={title} />
</>
);
}
16 changes: 12 additions & 4 deletions frontend/src/Components/NewCharts/PieChart.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Pie } from 'react-chartjs-2';
import DataLoading from '../Charts/ChartPrimitives/DataLoading';

export default function PieChart({
data,
Expand Down Expand Up @@ -31,6 +32,9 @@ export default function PieChart({
return `${context.parsed}%`;
},
},
titleColor: '#000',
bodyColor: '#000',
backgroundColor: 'rgba(255, 255, 255, 1.0)',
},
title: {
display: displayTitle,
Expand All @@ -57,20 +61,20 @@ export default function PieChart({
}
const text = `${chart.data.labels[index]}: ${chart.data.datasets[0].data[index]}%`;
const textWidth = ctx.measureText(text).width;
ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
const height = y - 15 - offsetHeight;
ctx.fillRect(x - (textWidth + 10) / 2, height, textWidth + 10, 20);

ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.beginPath();
ctx.moveTo(x, y + 15 - offsetHeight);
ctx.lineTo(x - 10, y - 5 - offsetHeight);
ctx.lineTo(x + 10, y - 5 - offsetHeight);
ctx.fill();
ctx.restore();

ctx.font = '12px Arial';
ctx.fillStyle = 'white';
ctx.font = '14px Arial';
ctx.fillStyle = 'black';
ctx.fillText(text, x - textWidth / 2, y - offsetHeight);
ctx.restore();
}
Expand Down Expand Up @@ -98,6 +102,10 @@ export default function PieChart({

const noData = data.datasets[0].data.every((v) => parseInt(v, 10) === 0);

if (!data.datasets.length) {
return <DataLoading />;
}

return (
<>
{noData && <div style={{ textAlign: 'center' }}>No Data Found</div>}
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/util/tooltipLanguage.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions nc/prime_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"nc:agency-api-searches-by-type",
"nc:agency-api-contraband-hit-rate",
"nc:agency-api-use-of-force",
"nc:stops-by-count",
"nc:stop-purpose-groups",
"nc:stops-grouped-by-purpose",
)
DEFAULT_CUTOFF_SECS = 4

Expand Down
3 changes: 3 additions & 0 deletions nc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
path(
"api/agency/<agency_id>/stops-by-count/",
views.AgencyTrafficStopsByCountView.as_view(),
name="stops-by-count",
),
path(
"api/agency/<agency_id>/stop-purpose-groups/",
views.AgencyStopPurposeGroupView.as_view(),
name="stop-purpose-groups",
),
path(
"api/agency/<agency_id>/stops-grouped-by-purpose/",
views.AgencyStopGroupByPurposeView.as_view(),
name="stops-grouped-by-purpose",
),
]
20 changes: 16 additions & 4 deletions nc/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def get(self, request, agency_id):

qs = qs.values(*qs_values).annotate(count=Sum("count")).order_by(date_precision)
if qs.count() == 0:
return Response(data=[], status=200)
return Response(data={"labels": [], "datasets": []}, status=200)
df = pd.DataFrame(qs)
unique_x_range = df[date_precision].unique()
pivot_df = df.pivot(index=date_precision, columns=qs_df_cols, values="count").fillna(
Expand All @@ -464,6 +464,12 @@ def get(self, request, agency_id):


class AgencyStopPurposeGroupView(APIView):
def get_values(self, df, stop_purpose, years_len):
if stop_purpose and stop_purpose in df:
return list(df[stop_purpose].values)
else:
return [0] * years_len

def get(self, request, agency_id):
qs = StopSummary.objects.all()
agency_id = int(agency_id)
Expand All @@ -480,30 +486,34 @@ def get(self, request, agency_id):
.annotate(count=Sum("count"))
.order_by("year")
)
if qs.count() == 0:
return Response(data={"labels": [], "datasets": []}, status=200)

df = pd.DataFrame(qs)
unique_years = df.year.unique()
pivot_df = df.pivot(index="year", columns="stop_purpose_group", values="count").fillna(
value=0
)
df = pd.DataFrame(pivot_df)
years_len = len(unique_years)
data = {
"labels": unique_years,
"datasets": [
{
"label": StopPurposeGroup.SAFETY_VIOLATION,
"data": list(df[StopPurposeGroup.SAFETY_VIOLATION].values),
"data": self.get_values(df, StopPurposeGroup.SAFETY_VIOLATION, years_len),
"borderColor": "#7F428A",
"backgroundColor": "#CFA9D6",
},
{
"label": StopPurposeGroup.REGULATORY_EQUIPMENT,
"data": list(df[StopPurposeGroup.REGULATORY_EQUIPMENT].values),
"data": self.get_values(df, StopPurposeGroup.REGULATORY_EQUIPMENT, years_len),
"borderColor": "#b36800",
"backgroundColor": "#ffa500",
},
{
"label": StopPurposeGroup.OTHER,
"data": list(df[StopPurposeGroup.OTHER].values),
"data": self.get_values(df, StopPurposeGroup.OTHER, years_len),
"borderColor": "#1B4D3E",
"backgroundColor": "#ACE1AF",
},
Expand Down Expand Up @@ -575,6 +585,8 @@ def get(self, request, agency_id):
.annotate(count=Sum("count"))
.order_by("year")
)
if qs.count() == 0:
return Response(data={"labels": [], "datasets": []}, status=200)
df = pd.DataFrame(qs)
unique_years = df.year.unique()
pivot_table = pd.pivot_table(
Expand Down

0 comments on commit 535fd18

Please sign in to comment.