Skip to content

Commit f4476c3

Browse files
committed
Merge branch 'improvement/add-long-term-x-axis-date-format' into q/1.0
2 parents 0e79c51 + b5b1f51 commit f4476c3

File tree

3 files changed

+141
-9
lines changed

3 files changed

+141
-9
lines changed

src/lib/components/date/FormattedDateTime.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ export const DAY_MONTH_ABBREVIATED_HOUR_MINUTE = Intl.DateTimeFormat('en-GB', {
5454
hour12: false,
5555
});
5656

57+
/**
58+
* @description Year month day formatter, without time. Used for describing long term date.
59+
* @example 2025-01-01
60+
*/
61+
export const YEAR_MONTH_DAY_FORMATTER = Intl.DateTimeFormat('en-CA', {
62+
year: 'numeric',
63+
month: '2-digit',
64+
day: '2-digit',
65+
});
66+
5767
type FormattedDateTimeProps = {
5868
format:
5969
| 'date'
@@ -65,7 +75,8 @@ type FormattedDateTimeProps = {
6575
| 'day-month-abbreviated-hour-minute'
6676
| 'day-month-abbreviated-hour-minute-second'
6777
| 'long-date'
68-
| 'chart-date';
78+
| 'chart-date'
79+
| 'year-month-day';
6980

7081
value: Date;
7182
};
@@ -198,6 +209,8 @@ export const FormattedDateTime = ({
198209
return <>{LONG_DATE_FORMATER.format(value)}</>;
199210
case 'chart-date':
200211
return <>{DAY_MONTH_FORMATER.format(value).replace(/[ ,]/g, '')}</>;
212+
case 'year-month-day':
213+
return <>{YEAR_MONTH_DAY_FORMATTER.format(value)}</>;
201214
default:
202215
return <></>;
203216
}

src/lib/components/linetimeseriechart/linetimeseriechart.component.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
YAxis,
99
CartesianGrid,
1010
} from 'recharts';
11-
import { useMemo, useRef } from 'react';
11+
import { useCallback, useMemo, useRef } from 'react';
1212
import { useTheme } from 'styled-components';
1313
import { addMissingDataPoint } from '../linetemporalchart/ChartUtil';
1414
import styled from 'styled-components';
@@ -23,6 +23,7 @@ import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
2323
import {
2424
DAY_MONTH_ABBREVIATED_HOUR_MINUTE,
2525
FormattedDateTime,
26+
YEAR_MONTH_DAY_FORMATTER,
2627
} from '../date/FormattedDateTime';
2728

2829
const LineTemporalChartWrapper = styled.div`
@@ -129,6 +130,12 @@ export type LineChartProps = (
129130
label: string;
130131
}[];
131132
isLoading?: boolean;
133+
/**
134+
* The format of the x axis, default is 'date-time' which is like 01 Sep 16:00
135+
* If you want to display the date only, you can set it to 'date' which is like 2025-09-01
136+
* This will affect the format of the tooltip as well
137+
*/
138+
timeFormat?: 'date-time' | 'date';
132139
yAxisTitle?: string;
133140
helpText?: string;
134141
};
@@ -138,6 +145,7 @@ const CustomTooltip = ({
138145
payload,
139146
label,
140147
unitLabel,
148+
timeFormat,
141149
}: {
142150
active?: boolean;
143151
payload?: Array<{
@@ -148,6 +156,7 @@ const CustomTooltip = ({
148156
}>;
149157
label?: string;
150158
unitLabel?: string;
159+
timeFormat?: 'date-time' | 'date';
151160
}) => {
152161
if (!active || !payload || !payload.length || !label) return null;
153162
// We can't use the default itemSorter method because it's a custom tooltip.
@@ -169,7 +178,11 @@ const CustomTooltip = ({
169178
<TooltipContainer>
170179
<TooltipTime>
171180
<FormattedDateTime
172-
format="day-month-abbreviated-hour-minute-second"
181+
format={
182+
timeFormat === 'date-time'
183+
? 'day-month-abbreviated-hour-minute-second'
184+
: 'long-date'
185+
}
173186
value={new Date(label)}
174187
/>
175188
</TooltipTime>
@@ -205,6 +218,7 @@ export function LineTimeSerieChart({
205218
duration,
206219
unitRange,
207220
isLoading = false,
221+
timeFormat = 'date-time',
208222
yAxisType = 'default',
209223
yAxisTitle,
210224
helpText,
@@ -393,12 +407,16 @@ export function LineTimeSerieChart({
393407
}, [series, getColor]);
394408

395409
// Format time for display the tick in the x axis
396-
const formatTime = useMemo(
397-
() => (timestamp: number) => {
410+
const formatXAxisLabel = useCallback(
411+
(timestamp: number) => {
398412
const date = new Date(timestamp);
399-
return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
413+
return timeFormat === 'date-time'
414+
? DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '')
415+
: timeFormat === 'date'
416+
? YEAR_MONTH_DAY_FORMATTER.format(date)
417+
: '';
400418
},
401-
[],
419+
[timeFormat],
402420
);
403421

404422
return (
@@ -438,7 +456,7 @@ export function LineTimeSerieChart({
438456
type="number"
439457
domain={['dataMin', 'dataMax']}
440458
ticks={xAxisTicks}
441-
tickFormatter={formatTime}
459+
tickFormatter={formatXAxisLabel}
442460
tickCount={5}
443461
tick={{
444462
fill: theme.textSecondary,
@@ -473,7 +491,11 @@ export function LineTimeSerieChart({
473491
}}
474492
tickFormatter={(value) => Math.round(value).toString()}
475493
/>
476-
<Tooltip content={<CustomTooltip unitLabel={unitLabel} />} />
494+
<Tooltip
495+
content={
496+
<CustomTooltip unitLabel={unitLabel} timeFormat={timeFormat} />
497+
}
498+
/>
477499
{/* Add horizontal line at y=0 for symmetrical charts */}
478500
{yAxisType === 'symmetrical' && (
479501
<ReferenceLine y={0} stroke={theme.border} />

stories/linetimeseriechart.stories.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ const meta: Meta<typeof LineTimeSerieChart> = {
6464
options: ['default', 'percentage', 'symmetrical'],
6565
},
6666
yAxisTitle: { control: 'text' },
67+
timeFormat: {
68+
control: 'select',
69+
options: ['date-time', 'date'],
70+
},
6771
},
6872
};
6973

@@ -405,6 +409,74 @@ const irregularIntervalData = [
405409
[1740424900, '46.92'], // +1100 seconds (18.3 minutes) - under 2 intervals
406410
];
407411

412+
// Data spanning several months - multi-month dataset
413+
const longTermPrometheusData: [number, string][] = [
414+
// January 2025
415+
[1735689600, '42.15'], // Jan 1, 2025
416+
[1735776000, '38.92'], // Jan 2, 2025
417+
[1735862400, '55.33'], // Jan 3, 2025
418+
[1735948800, '67.88'], // Jan 4, 2025
419+
[1736035200, '44.21'], // Jan 5, 2025
420+
[1736121600, '72.15'], // Jan 6, 2025
421+
[1736208000, '39.67'], // Jan 7, 2025
422+
[1736294400, '58.44'], // Jan 8, 2025
423+
[1736380800, '63.92'], // Jan 9, 2025
424+
[1736467200, '41.33'], // Jan 10, 2025
425+
[1736553600, '76.88'], // Jan 11, 2025
426+
[1736640000, '52.15'], // Jan 12, 2025
427+
[1736726400, '48.67'], // Jan 13, 2025
428+
[1736812800, '69.33'], // Jan 14, 2025
429+
[1736899200, '35.88'], // Jan 15, 2025
430+
// February 2025
431+
[1738368000, '81.15'], // Feb 1, 2025
432+
[1738454400, '47.67'], // Feb 2, 2025
433+
[1738540800, '54.33'], // Feb 3, 2025
434+
[1738627200, '62.88'], // Feb 4, 2025
435+
[1738713600, '38.15'], // Feb 5, 2025
436+
[1738800000, '73.67'], // Feb 6, 2025
437+
[1738886400, '45.33'], // Feb 7, 2025
438+
[1738972800, '59.88'], // Feb 8, 2025
439+
[1739059200, '51.15'], // Feb 9, 2025
440+
[1739145600, '66.67'], // Feb 10, 2025
441+
[1739232000, '43.33'], // Feb 11, 2025
442+
[1739318400, '78.88'], // Feb 12, 2025
443+
[1739404800, '36.15'], // Feb 13, 2025
444+
[1739491200, '64.67'], // Feb 14, 2025
445+
[1739577600, '49.33'], // Feb 15, 2025
446+
// March 2025
447+
[1740787200, '71.88'], // Mar 1, 2025
448+
[1740873600, '42.15'], // Mar 2, 2025
449+
[1740960000, '57.67'], // Mar 3, 2025
450+
[1741046400, '68.33'], // Mar 4, 2025
451+
[1741132800, '34.88'], // Mar 5, 2025
452+
[1741219200, '75.15'], // Mar 6, 2025
453+
[1741305600, '48.67'], // Mar 7, 2025
454+
[1741392000, '53.33'], // Mar 8, 2025
455+
[1741478400, '61.88'], // Mar 9, 2025
456+
[1741564800, '37.15'], // Mar 10, 2025
457+
[1741651200, '74.67'], // Mar 11, 2025
458+
[1741737600, '44.33'], // Mar 12, 2025
459+
[1741824000, '58.88'], // Mar 13, 2025
460+
[1741910400, '52.15'], // Mar 14, 2025
461+
[1741996800, '67.67'], // Mar 15, 2025
462+
// April 2025
463+
[1743465600, '41.33'], // Apr 1, 2025
464+
[1743552000, '76.88'], // Apr 2, 2025
465+
[1743638400, '35.15'], // Apr 3, 2025
466+
[1743724800, '63.67'], // Apr 4, 2025
467+
[1743811200, '50.33'], // Apr 5, 2025
468+
[1743897600, '72.88'], // Apr 6, 2025
469+
[1743984000, '39.15'], // Apr 7, 2025
470+
[1744070400, '56.67'], // Apr 8, 2025
471+
[1744156800, '65.33'], // Apr 9, 2025
472+
[1744243200, '33.88'], // Apr 10, 2025
473+
[1744329600, '77.15'], // Apr 11, 2025
474+
[1744416000, '46.67'], // Apr 12, 2025
475+
[1744502400, '54.33'], // Apr 13, 2025
476+
[1744588800, '60.88'], // Apr 14, 2025
477+
[1744675200, '49.22'], // Apr 15, 2025
478+
];
479+
408480
export const PercentageChartExample: Story = {
409481
args: {
410482
series: [
@@ -425,6 +497,7 @@ export const PercentageChartExample: Story = {
425497
yAxisTitle: '',
426498
interval: SAMPLE_FREQUENCY_LAST_TWENTY_FOUR_HOURS,
427499
duration: SAMPLE_DURATION_LAST_TWENTY_FOUR_HOURS,
500+
xAxisFormat: 'date-time',
428501
},
429502
};
430503
const UNIT_RANGE_BS = [
@@ -537,3 +610,27 @@ export const IrregularIntervalsExample: Story = {
537610
duration: SAMPLE_DURATION_LAST_TWENTY_FOUR_HOURS,
538611
},
539612
};
613+
614+
export const DateFormatExample: Story = {
615+
args: {
616+
series: [
617+
{
618+
data: longTermPrometheusData,
619+
resource: 'ip-10-160-122-207.eu-north-1.compute.internal',
620+
metricPrefix: 'instance:10.160.122.207:9100',
621+
getTooltipLabel: (prefix, resource) => `${resource}`,
622+
},
623+
],
624+
title: 'Long term data',
625+
height: 200,
626+
startingTimeStamp: longTermPrometheusData[0][0],
627+
isLoading: false,
628+
isLegendHidden: false,
629+
helpText: 'This is the help text',
630+
interval: 60 * 60 * 24, // 1 day
631+
duration:
632+
longTermPrometheusData[longTermPrometheusData.length - 1][0] -
633+
longTermPrometheusData[0][0],
634+
timeFormat: 'date',
635+
},
636+
};

0 commit comments

Comments
 (0)