Skip to content

Commit c7e5da5

Browse files
committed
ARTESCA-14587: Adjust the chart base on the valueBase
1 parent 1e4855b commit c7e5da5

File tree

2 files changed

+137
-43
lines changed

2 files changed

+137
-43
lines changed

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

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ import {
1818
fontWeight,
1919
lineTimeSeriesColorRange,
2020
} from '../../style/theme';
21-
import { ChartTitleText } from '../text/Text.component';
21+
import { ChartTitleText, SmallerText } from '../text/Text.component';
2222
import { Loader } from '../loader/Loader.component';
2323
import { spacing } from '../../spacing';
2424
import { getUnitLabel } from '../linetemporalchart/ChartUtil';
25+
import { Icon } from '../icon/Icon.component';
26+
import { Tooltip as TooltipComponent } from '../tooltip/Tooltip.component';
27+
import {
28+
DAY_MONTH_ABBREVIATED_HOUR_MINUTE,
29+
FormattedDateTime,
30+
} from '../date/FormattedDateTime';
2531

2632
const LineTemporalChartWrapper = styled.div`
2733
display: flex;
@@ -168,16 +174,10 @@ const CustomTooltip = ({
168174
return (
169175
<TooltipContainer>
170176
<TooltipTime>
171-
{new Date(label)
172-
.toLocaleString('en-GB', {
173-
day: 'numeric',
174-
month: 'short',
175-
hour: '2-digit',
176-
minute: '2-digit',
177-
second: '2-digit',
178-
hour12: false,
179-
})
180-
.replace(',', '')}
177+
<FormattedDateTime
178+
format="day-month-abbreviated-hour-minute-second"
179+
value={new Date(label)}
180+
/>
181181
</TooltipTime>
182182
{sortedPayload.map((entry, index) => (
183183
<TooltipValue key={index}>
@@ -187,9 +187,7 @@ const CustomTooltip = ({
187187
<TooltipInstanceValue>
188188
{isNaN(Number(entry.value))
189189
? '-'
190-
: typeof entry.value === 'number'
191-
? `${Math.round(entry.value * 100) / 100}${unitLabel}`
192-
: `${Number(entry.value).toFixed(2)}${unitLabel}`}
190+
: `${Number(entry.value).toFixed(2)}${unitLabel}`}
193191
</TooltipInstanceValue>
194192
</TooltipContent>
195193
</TooltipValue>
@@ -262,7 +260,8 @@ export function LineTimeSerieChart({
262260
}));
263261

264262
// 2. Convert directly to Recharts format
265-
const rechartsData: Record<
263+
// Initialize an object to hold data points by timestamp
264+
const dataPointsByTime: Record<
266265
number,
267266
{ timestamp: number } & Record<string, string | number | null>
268267
> = {};
@@ -278,17 +277,17 @@ export function LineTimeSerieChart({
278277
const timestamp =
279278
typeof point[0] === 'number' ? point[0] * 1000 : Number(point[0]);
280279
const value = point[1];
281-
282-
if (!rechartsData[timestamp]) {
283-
rechartsData[timestamp] = { timestamp };
280+
// Initialize this timestamp if it doesn't exist
281+
if (!dataPointsByTime[timestamp]) {
282+
dataPointsByTime[timestamp] = { timestamp };
284283
}
285-
286-
rechartsData[timestamp][label] = value;
284+
// Add this metric's value to the data point, and convert the value to a number if it's a string
285+
dataPointsByTime[timestamp][label] =
286+
typeof value === 'string' ? Number(value) : value;
287287
});
288288
});
289-
290289
// Convert object to array for Recharts
291-
return Object.values(rechartsData).sort(
290+
return Object.values(dataPointsByTime).sort(
292291
(
293292
a: { timestamp: number } & Record<string, string | number | null>,
294293
b: { timestamp: number } & Record<string, string | number | null>,
@@ -320,9 +319,14 @@ export function LineTimeSerieChart({
320319
return exactEvenTicks;
321320
}, [chartData]);
322321

323-
const { topValue, unitLabel } = useMemo(() => {
324-
if (yAxisType === 'percentage') return { topValue: 100, unitLabel: '%' };
325-
if (!unitRange || !chartData.length) return { topValue: 0, unitLabel: '' };
322+
// 3. Transform the data base on the valuebase
323+
const { topValue, unitLabel, rechartsData } = useMemo(() => {
324+
if (yAxisType === 'percentage')
325+
return {
326+
topValue: 100,
327+
unitLabel: '%',
328+
rechartsData: chartData,
329+
};
326330

327331
const values = chartData.flatMap((dataPoint) =>
328332
Object.entries(dataPoint)
@@ -338,12 +342,23 @@ export function LineTimeSerieChart({
338342
const top = Math.abs(Math.max(...values));
339343
const bottom = Math.abs(Math.min(...values));
340344
const maxValue = Math.max(top, bottom);
341-
const roundedMax = Math.ceil(maxValue / 10) * 10;
342345

343-
return {
344-
topValue: roundedMax,
345-
unitLabel: getUnitLabel(unitRange, maxValue).unitLabel,
346-
};
346+
const { valueBase, unitLabel } = getUnitLabel(unitRange ?? [], maxValue);
347+
348+
const topValue = Math.ceil(maxValue / valueBase / 10) * 10;
349+
350+
// Convert the data points in the same memo
351+
const rechartsData = chartData.map((dataPoint) => {
352+
const normalizedDataPoint = { ...dataPoint };
353+
Object.entries(dataPoint).forEach(([key, value]) => {
354+
if (key !== 'timestamp' && typeof value === 'number') {
355+
normalizedDataPoint[key] = value / valueBase;
356+
}
357+
});
358+
return normalizedDataPoint;
359+
});
360+
361+
return { topValue, unitLabel, rechartsData };
347362
}, [chartData, yAxisType, unitRange]);
348363

349364
// Group series by resource and create color mapping
@@ -383,14 +398,7 @@ export function LineTimeSerieChart({
383398
const formatTime = useMemo(
384399
() => (timestamp: number) => {
385400
const date = new Date(timestamp);
386-
return date
387-
.toLocaleDateString('en-GB', {
388-
day: 'numeric',
389-
month: 'short',
390-
hour: '2-digit',
391-
minute: '2-digit',
392-
})
393-
.replace(',', '');
401+
return DAY_MONTH_ABBREVIATED_HOUR_MINUTE.format(date).replace(',', '');
394402
},
395403
[],
396404
);
@@ -401,11 +409,19 @@ export function LineTimeSerieChart({
401409
<ChartTitleText>
402410
{title} {unitLabel && `(${unitLabel})`}
403411
</ChartTitleText>
412+
{helpText && (
413+
<TooltipComponent
414+
placement={'right'}
415+
overlay={<SmallerText>{helpText}</SmallerText>}
416+
>
417+
<Icon name="Info" color={theme.buttonSecondary} />
418+
</TooltipComponent>
419+
)}
404420
{isLoading && <Loader />}
405421
</ChartHeader>
406422
<ResponsiveContainer width="100%" height={height}>
407423
<LineChart
408-
data={chartData}
424+
data={rechartsData}
409425
ref={chartRef}
410426
margin={{ top: 0, right: 0, bottom: 0, left: 0 }}
411427
aria-label={`Time series chart for ${title}`}

stories/linetimeseriechart.stories.tsx

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ const meta: Meta<typeof LineTimeSerieChart> = {
3232
startingTimeStamp: { control: 'number' },
3333
unitRange: { control: 'object' },
3434
isLoading: { control: 'boolean' },
35-
isLegendHidden: { control: 'boolean' },
3635
yAxisType: {
3736
control: 'select',
3837
options: ['default', 'percentage', 'symmetrical'],
@@ -44,7 +43,6 @@ const meta: Meta<typeof LineTimeSerieChart> = {
4443
export default meta;
4544
type Story = StoryObj<typeof ChartWithProviders>;
4645

47-
// The Prometheus dataset converted for use with LineTemporalChartV2
4846
const prometheusData = [
4947
[1740405600, '47.554166666666674'],
5048
[1740406320, '53.00833333333337'],
@@ -293,6 +291,68 @@ const prometheusData4 = [
293291
[1740492000, '185.90'],
294292
];
295293

294+
const prometheusData5 = [
295+
[1740405600, '12850.45'],
296+
[1740406320, '21780.92'],
297+
[1740407760, '8320.15'],
298+
[1740408480, '16420.78'],
299+
[1740409200, '21950.34'],
300+
[1740409920, '9280.67'],
301+
[1740410640, '18605.89'],
302+
[1740411360, '12450.23'],
303+
[1740412080, '21308.56'],
304+
[1740412800, '18808.90'],
305+
[1740413520, '15305.67'],
306+
[1740414240, '24550.45'],
307+
[1740415680, '10205.89'],
308+
[1740416400, '19208.90'],
309+
[1740417120, '24802.34'],
310+
[1740417840, '13402.56'],
311+
[1740418560, '21450.78'],
312+
[1740419280, '18220.34'],
313+
[1740420000, '26608.90'],
314+
[1740420720, '19380.45'],
315+
[1740421440, '23350.67'],
316+
[1740422160, '19920.45'],
317+
[1740422880, '15480.23'],
318+
[1740423600, '28580.90'],
319+
[1740467520, '17280.45'],
320+
[1740468240, '24750.67'],
321+
[1740468960, '18420.34'],
322+
[1740469680, '23480.90'],
323+
[1740470400, '19850.67'],
324+
[1740471120, '27320.45'],
325+
[1740471840, '19720.34'],
326+
[1740472560, '24405.67'],
327+
[1740473280, '18502.89'],
328+
[1740474000, '27908.45'],
329+
[1740474720, '16205.67'],
330+
[1740475440, '23602.34'],
331+
[1740476160, '19305.89'],
332+
[1740476880, '24450.67'],
333+
[1740477600, '18858.90'],
334+
[1740478320, '26492.34'],
335+
[1740479040, '19588.90'],
336+
[1740479760, '28288.45'],
337+
[1740480480, '19765.67'],
338+
[1740481200, '23398.90'],
339+
[1740481920, '19492.34'],
340+
[1740482640, '25929.45'],
341+
[1740483360, '18329.67'],
342+
[1740484080, '24659.89'],
343+
[1740484800, '19459.23'],
344+
[1740485520, '27559.67'],
345+
[1740486240, '18259.89'],
346+
[1740486960, '25689.90'],
347+
[1740487680, '19959.34'],
348+
[1740488400, '28359.67'],
349+
[1740489120, '19489.90'],
350+
[1740489840, '26429.34'],
351+
[1740490560, '19729.45'],
352+
[1740491280, '28289.67'],
353+
[1740492000, '19859.90'],
354+
];
355+
296356
export const PercentageChartExample: Story = {
297357
args: {
298358
series: [
@@ -307,16 +367,16 @@ export const PercentageChartExample: Story = {
307367
title: 'CPU Usage',
308368
height: 200,
309369
startingTimeStamp: prometheusData[0][0],
310-
unitRange: [{ value: 1, unitLabel: '%' }],
311370
isLoading: false,
312371
isLegendHidden: false,
372+
helpText: 'This is the help text',
313373
yAxisType: 'percentage',
314374
yAxisTitle: '',
315375
},
316376
};
317377
const UNIT_RANGE_BS = [
318378
{
319-
threshold: 0,
379+
threshold: 1,
320380
label: 'B/s',
321381
},
322382
{
@@ -382,3 +442,21 @@ export const SymmetricalAxisExample: Story = {
382442
yAxisTitle: 'in(+)/out(-)',
383443
},
384444
};
445+
export const AutoUnitChartExample: Story = {
446+
args: {
447+
series: [
448+
{
449+
data: prometheusData5,
450+
resource: 'ip-10-160-122-207.eu-north-1.compute.internal',
451+
metricPrefix: 'instance:10.160.122.207:9100',
452+
getTooltipLabel: (prefix, resource) => `${resource}`,
453+
getLegendLabel: (prefix, resource) => `${resource}`,
454+
},
455+
],
456+
title: 'Disk Throughput',
457+
startingTimeStamp: prometheusData5[0][0],
458+
height: 200,
459+
unitRange: UNIT_RANGE_BS,
460+
yAxisType: 'default',
461+
},
462+
};

0 commit comments

Comments
 (0)