From cd8963b7b59a7d4fc3076d9bd4d40b9de7f9c85c Mon Sep 17 00:00:00 2001 From: Devin Matte Date: Thu, 12 Sep 2024 20:48:37 -0400 Subject: [PATCH 1/2] Adding missing watermarks, mobile fixes and headway calcs --- .../ByHourHistogram/ByHourHistogram.tsx | 32 ++++++++++++++++--- .../TimeSeriesChart/TimeSeriesChart.tsx | 4 ++- modules/service/DailyServiceHistogram.tsx | 14 +++++--- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/common/components/charts/ByHourHistogram/ByHourHistogram.tsx b/common/components/charts/ByHourHistogram/ByHourHistogram.tsx index 23a672b44..a127353b4 100644 --- a/common/components/charts/ByHourHistogram/ByHourHistogram.tsx +++ b/common/components/charts/ByHourHistogram/ByHourHistogram.tsx @@ -1,5 +1,6 @@ -import React, { useMemo } from 'react'; +import React, { useMemo, useRef } from 'react'; import { Bar as BarChart } from 'react-chartjs-2'; +import ChartjsPluginWatermark from 'chartjs-plugin-watermark'; import { Chart as ChartJS, CategoryScale, @@ -11,6 +12,7 @@ import { import Color from 'color'; import { useBreakpoint } from '../../../hooks/useBreakpoint'; +import { watermarkLayout } from '../../../constants/charts'; import type { ByHourDataset, DisplayStyle, ValueAxis as ValueAxis } from './types'; import { resolveStyle } from './styles'; @@ -20,6 +22,8 @@ interface Props { style?: Partial; data: ByHourDataset[]; valueAxis: ValueAxis; + /** Whether the dataset is roundtrips, and we want to additionally convert and show the values as headways */ + datasetRoundTrips?: boolean; } const allTimeLabels = ['AM', 'PM'] @@ -51,11 +55,17 @@ const stripZeroHoursAndRotateMidnightToEnd = ( }; export const ByHourHistogram: React.FC = (props) => { - const { data: dataWithZeros, valueAxis, style: baseStyle = null } = props; + const { + data: dataWithZeros, + valueAxis, + style: baseStyle = null, + datasetRoundTrips = false, + } = props; const { data, timeLabels } = useMemo( () => stripZeroHoursAndRotateMidnightToEnd(dataWithZeros), [dataWithZeros] ); + const ref = useRef(); const isMobile = !useBreakpoint('md'); const chartData = useMemo(() => { @@ -96,6 +106,9 @@ export const ByHourHistogram: React.FC = (props) => { }, }, }, + responsive: true, + maintainAspectRatio: false, + watermark: watermarkLayout(isMobile), plugins: { legend: { display: true, @@ -109,13 +122,22 @@ export const ByHourHistogram: React.FC = (props) => { const dataset = data[datasetIndex]; const value = dataset.data[dataIndex]; const { label } = dataset; - return `${label}: ${value} ${valueAxis.tooltipItemLabel ?? ''}`.trim(); + return `${label}: ${value} ${valueAxis.tooltipItemLabel ?? ''} ${datasetRoundTrips ? `(${Math.round((60 / value) * 2)}m headways)` : ''}`.trim(); }, }, }, }, }; - }, [valueAxis.title, valueAxis.tooltipItemLabel, data]); + }, [valueAxis.title, valueAxis.tooltipItemLabel, isMobile, data, datasetRoundTrips]); - return ; + return ( + + ); }; diff --git a/common/components/charts/TimeSeriesChart/TimeSeriesChart.tsx b/common/components/charts/TimeSeriesChart/TimeSeriesChart.tsx index 20fb51fe1..1cfc65241 100644 --- a/common/components/charts/TimeSeriesChart/TimeSeriesChart.tsx +++ b/common/components/charts/TimeSeriesChart/TimeSeriesChart.tsx @@ -1,5 +1,6 @@ import React, { useMemo } from 'react'; import { Line as LineChart } from 'react-chartjs-2'; +import ChartjsPluginWatermark from 'chartjs-plugin-watermark'; import { Chart as ChartJS, CategoryScale, @@ -17,7 +18,6 @@ import { } from 'chart.js'; import Annotation from 'chartjs-plugin-annotation'; import ChartDataLabels from 'chartjs-plugin-datalabels'; -import ChartjsPluginWatermark from 'chartjs-plugin-watermark'; import 'chartjs-adapter-date-fns'; import type { ChartData } from 'chart.js'; @@ -26,6 +26,7 @@ import { useBreakpoint } from '../../../hooks/useBreakpoint'; import { ChartDiv } from '../ChartDiv'; import { CHART_COLORS, COLORS } from '../../../constants/colors'; +import { watermarkLayout } from '../../../constants/charts'; import type { AppliedDisplayStyle, Benchmark, @@ -225,6 +226,7 @@ export const TimeSeriesChart = (props: Props) => { interaction: { intersect: false, }, + watermark: watermarkLayout(isMobile), plugins: { datalabels: { display: false, diff --git a/modules/service/DailyServiceHistogram.tsx b/modules/service/DailyServiceHistogram.tsx index 9e5ef76c2..a06b7406b 100644 --- a/modules/service/DailyServiceHistogram.tsx +++ b/modules/service/DailyServiceHistogram.tsx @@ -5,6 +5,7 @@ import { ByHourHistogram } from '../../common/components/charts/ByHourHistogram' import { useDelimitatedRoute } from '../../common/utils/router'; import { prettyDate } from '../../common/utils/date'; import { ButtonGroup } from '../../common/components/general/ButtonGroup'; +import { CarouselGraphDiv } from '../../common/components/charts/CarouselGraphDiv'; interface Props { scheduledService: ScheduledService; @@ -39,11 +40,14 @@ export const DailyServiceHistogram: React.FC = (props) => { return ( <> - + + +
Date: Fri, 13 Sep 2024 14:38:11 -0400 Subject: [PATCH 2/2] Fix round trip numbers --- .../ByHourHistogram/ByHourHistogram.tsx | 25 +++++++++++++------ modules/service/DailyServiceHistogram.tsx | 4 +-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/common/components/charts/ByHourHistogram/ByHourHistogram.tsx b/common/components/charts/ByHourHistogram/ByHourHistogram.tsx index a127353b4..e0bf4dbe7 100644 --- a/common/components/charts/ByHourHistogram/ByHourHistogram.tsx +++ b/common/components/charts/ByHourHistogram/ByHourHistogram.tsx @@ -11,6 +11,7 @@ import { } from 'chart.js'; import Color from 'color'; +import type { Context } from 'chartjs-plugin-datalabels'; import { useBreakpoint } from '../../../hooks/useBreakpoint'; import { watermarkLayout } from '../../../constants/charts'; import type { ByHourDataset, DisplayStyle, ValueAxis as ValueAxis } from './types'; @@ -68,6 +69,20 @@ export const ByHourHistogram: React.FC = (props) => { const ref = useRef(); const isMobile = !useBreakpoint('md'); + const tooltipFormat = React.useCallback( + ({ datasetIndex, dataIndex }: Context) => { + const dataset = data[datasetIndex]; + const value = dataset.data[dataIndex]; + const { label } = dataset; + + if (datasetRoundTrips) { + return `${label}: ${value} ${valueAxis.tooltipItemLabel ?? ''} (${Math.round(60 / value)}m headways)`.trim(); + } + return `${label}: ${value} ${valueAxis.tooltipItemLabel ?? ''}`.trim(); + }, + [data, datasetRoundTrips, valueAxis.tooltipItemLabel] + ); + const chartData = useMemo(() => { return { labels: timeLabels, @@ -118,17 +133,13 @@ export const ByHourHistogram: React.FC = (props) => { mode: 'index' as const, callbacks: { label: (context) => { - const { datasetIndex, dataIndex } = context; - const dataset = data[datasetIndex]; - const value = dataset.data[dataIndex]; - const { label } = dataset; - return `${label}: ${value} ${valueAxis.tooltipItemLabel ?? ''} ${datasetRoundTrips ? `(${Math.round((60 / value) * 2)}m headways)` : ''}`.trim(); + return tooltipFormat(context); }, }, }, }, }; - }, [valueAxis.title, valueAxis.tooltipItemLabel, isMobile, data, datasetRoundTrips]); + }, [valueAxis.title, isMobile, tooltipFormat]); return ( = (props) => { ref={ref} data={chartData} options={chartOptions} - height={isMobile ? 240 : 80} + height={isMobile ? 200 : 75} plugins={[ChartjsPluginWatermark]} /> ); diff --git a/modules/service/DailyServiceHistogram.tsx b/modules/service/DailyServiceHistogram.tsx index a06b7406b..f04013f40 100644 --- a/modules/service/DailyServiceHistogram.tsx +++ b/modules/service/DailyServiceHistogram.tsx @@ -28,12 +28,12 @@ export const DailyServiceHistogram: React.FC = (props) => { return [ { label: prettyDate(startDate), - data: startServiceLevels!, + data: startServiceLevels!.map((value) => value / 2), style: { opacity: 0.5 }, }, { label: prettyDate(endDate), - data: endServiceLevels!, + data: endServiceLevels!.map((value) => value / 2), }, ]; }, [scheduledService, dayKind]);