Skip to content

Commit 4eb5c04

Browse files
authored
fix(ClusterMetricsCores): format value and capacity same way (#1532)
1 parent e4cb52f commit 4eb5c04

File tree

12 files changed

+256
-80
lines changed

12 files changed

+256
-80
lines changed

src/components/FormattedBytes/FormattedBytes.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import type {FormatBytesArgs} from '../../utils/bytesParsers';
1+
import type {BytesSizes} from '../../utils/bytesParsers';
22
import {formatBytes} from '../../utils/bytesParsers';
3+
import type {FormatValuesArgs} from '../../utils/dataFormatters/common';
34

4-
type FormattedBytesProps = FormatBytesArgs;
5+
type FormattedBytesProps = FormatValuesArgs<BytesSizes>;
56

67
export const FormattedBytes = ({value, withSpeedLabel, ...params}: FormattedBytesProps) => {
78
const formatted = formatBytes({value, withSpeedLabel, ...params});

src/components/FormattedBytes/utils.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import type {FormatBytesArgs} from '../../utils/bytesParsers';
1+
import type {BytesSizes} from '../../utils/bytesParsers';
2+
import type {FormatValuesArgs} from '../../utils/dataFormatters/common';
23

34
import {FormattedBytes} from './FormattedBytes';
45

56
export const toFormattedSize = (
67
value: number | string | undefined,
7-
params?: Omit<FormatBytesArgs, 'value'>,
8+
params?: Omit<FormatValuesArgs<BytesSizes>, 'value'>,
89
) => {
910
if (!value) {
1011
return null;

src/containers/Cluster/ClusterDashboard/components/ClusterMetricsCores.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {DoughnutMetrics} from '../../../../components/DoughnutMetrics/DoughnutMetrics';
2-
import {formatNumberCustom} from '../../../../utils/dataFormatters/dataFormatters';
2+
import {formatNumber, formatNumericValues} from '../../../../utils/dataFormatters/dataFormatters';
33
import i18n from '../../i18n';
44
import type {ClusterMetricsCommonProps} from '../shared';
55
import {useDiagramValues} from '../utils';
@@ -9,7 +9,13 @@ import {ClusterMetricsCardDoughnut} from './ClusterMetricsCard';
99
interface ClusterMetricsCoresProps extends ClusterMetricsCommonProps {}
1010

1111
function formatCoresLegend({value, capacity}: {value: number; capacity: number}) {
12-
return `${formatNumberCustom(value)} / ${formatNumberCustom(capacity)}\n${i18n('context_cores')}`;
12+
let formatted = [];
13+
if (capacity < 10_000) {
14+
formatted = [formatNumber(Math.round(value)), formatNumber(Math.round(capacity))];
15+
} else {
16+
formatted = formatNumericValues(value, capacity, undefined, '', true);
17+
}
18+
return `${formatted[0]} / ${formatted[1]}\n${i18n('context_cores')}`;
1319
}
1420

1521
export function ClusterMetricsCores({value, capacity, ...rest}: ClusterMetricsCoresProps) {

src/utils/bytesParsers/formatBytes.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {GIGABYTE, KILOBYTE, MEGABYTE, TERABYTE} from '../constants';
2+
import type {FormatToSizeArgs, FormatValuesArgs} from '../dataFormatters/common';
23
import {formatNumber, roundToPrecision} from '../dataFormatters/dataFormatters';
34
import {UNBREAKABLE_GAP, isNumeric} from '../utils';
45

@@ -72,13 +73,7 @@ export const getSizeWithSignificantDigits = (value: number, significantDigits: n
7273
return size;
7374
};
7475

75-
interface FormatToSizeArgs {
76-
value: number;
77-
size?: BytesSizes;
78-
precision?: number;
79-
}
80-
81-
const formatToSize = ({value, size = 'mb', precision = 0}: FormatToSizeArgs) => {
76+
const formatToSize = ({value, size = 'mb', precision = 0}: FormatToSizeArgs<BytesSizes>) => {
8277
const result = roundToPrecision(Number(value) / sizes[size].value, precision);
8378

8479
return formatNumber(result);
@@ -92,14 +87,6 @@ const addSpeedLabel = (result: string, size: BytesSizes) => {
9287
return addSizeLabel(result, size) + i18n('perSecond');
9388
};
9489

95-
export type FormatBytesArgs = Omit<FormatToSizeArgs, 'value'> & {
96-
value: number | string | undefined | null;
97-
withSpeedLabel?: boolean;
98-
withSizeLabel?: boolean;
99-
significantDigits?: number;
100-
delimiter?: string;
101-
};
102-
10390
/**
10491
* @param significantDigits - number of digits above 3
10592
*/
@@ -111,7 +98,7 @@ export const formatBytes = ({
11198
significantDigits = 0,
11299
delimiter,
113100
...params
114-
}: FormatBytesArgs) => {
101+
}: FormatValuesArgs<BytesSizes>) => {
115102
if (!isNumeric(value)) {
116103
return '';
117104
}

src/utils/bytesParsers/i18n/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
"mb": "MB",
55
"gb": "GB",
66
"tb": "TB",
7+
"label_thousand": "k",
8+
"label_million": "m",
9+
"label_billion": "b",
10+
"label_trillion": "t",
711
"perSecond": "/s"
812
}

src/utils/bytesParsers/i18n/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import {registerKeysets} from '../../i18n';
22

33
import en from './en.json';
4-
import ru from './ru.json';
54

65
const COMPONENT = 'ydb-bytes-parsers';
76

8-
export default registerKeysets(COMPONENT, {ru, en});
7+
export default registerKeysets(COMPONENT, {en});

src/utils/bytesParsers/i18n/ru.json

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {UNBREAKABLE_GAP} from '../../utils';
2+
import {formatNumericValues} from '../dataFormatters';
3+
4+
describe('formatNumericValues', () => {
5+
it('should return ["", ""] when both value and total are undefined', () => {
6+
const result = formatNumericValues();
7+
expect(result).toEqual(['', '']);
8+
});
9+
10+
it('should format value correctly when total is undefined', () => {
11+
const result = formatNumericValues(1000);
12+
expect(result).toEqual([`1${UNBREAKABLE_GAP}k`, '']);
13+
});
14+
15+
it('should format total correctly when value is undefined', () => {
16+
const result = formatNumericValues(undefined, 1_000_000);
17+
expect(result).toEqual(['', `1${UNBREAKABLE_GAP}m`]);
18+
});
19+
20+
it('should format both value and total correctly', () => {
21+
const result = formatNumericValues(1024, 2048);
22+
expect(result).toEqual(['1', `2${UNBREAKABLE_GAP}k`]);
23+
});
24+
it('should format value with label if set', () => {
25+
const result = formatNumericValues(1024, 2048, undefined, undefined, true);
26+
expect(result).toEqual([`1${UNBREAKABLE_GAP}k`, `2${UNBREAKABLE_GAP}k`]);
27+
});
28+
29+
it('should return ["0", formattedTotal] when value is 0', () => {
30+
const result = formatNumericValues(0, 2048);
31+
expect(result).toEqual(['0', `2${UNBREAKABLE_GAP}k`]);
32+
});
33+
34+
it('should use provided size and delimiter', () => {
35+
const result = formatNumericValues(5120, 10240, 'billion', '/');
36+
expect(result).toEqual(['0', '0/b']);
37+
});
38+
39+
it('should handle non-numeric total gracefully', () => {
40+
const result = formatNumericValues(2048, 'Not a number' as any);
41+
expect(result).toEqual([`2${UNBREAKABLE_GAP}k`, '']);
42+
});
43+
});

src/utils/dataFormatters/__test__/formatStorageValues.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,14 @@ describe('formatStorageValues', () => {
2222
expect(result).toEqual(['1', `2${UNBREAKABLE_GAP}KB`]);
2323
});
2424

25-
it('should handle small value compared to total and increase precision', () => {
26-
const result = formatStorageValues(1, 1024);
27-
expect(result).toEqual(['0.001', `1${UNBREAKABLE_GAP}KB`]);
28-
});
29-
3025
it('should return ["0", formattedTotal] when value is 0', () => {
3126
const result = formatStorageValues(0, 2048);
3227
expect(result).toEqual(['0', `2${UNBREAKABLE_GAP}KB`]);
3328
});
3429

3530
it('should use provided size and delimiter', () => {
3631
const result = formatStorageValues(5120, 10240, 'mb', '/');
37-
expect(result).toEqual(['0.01', '0/MB']);
32+
expect(result).toEqual(['0', '0/MB']);
3833
});
3934

4035
it('should handle non-numeric total gracefully', () => {

src/utils/dataFormatters/common.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {isNumeric} from '../utils';
2+
3+
export interface FormatToSizeArgs<T> {
4+
value: number;
5+
size?: T;
6+
precision?: number;
7+
}
8+
9+
export type FormatValuesArgs<T> = Omit<FormatToSizeArgs<T>, 'value'> & {
10+
value: number | string | undefined | null;
11+
withSpeedLabel?: boolean;
12+
withSizeLabel?: boolean;
13+
significantDigits?: number;
14+
delimiter?: string;
15+
};
16+
17+
export function formatValues<T>(
18+
formatter: (args: FormatValuesArgs<T>) => string,
19+
sizeGetter: (value: number, significantDigits: number) => T,
20+
value?: number,
21+
total?: number,
22+
size?: T,
23+
delimiter?: string,
24+
withValueLabel = false,
25+
) {
26+
let calculatedSize = sizeGetter(Number(value), 0);
27+
let valueWithSizeLabel = true;
28+
let valuePrecision = 0;
29+
30+
if (isNumeric(total)) {
31+
calculatedSize = sizeGetter(Number(total), 0);
32+
valueWithSizeLabel = withValueLabel;
33+
valuePrecision = 1;
34+
}
35+
36+
const formattedValue = formatter({
37+
value,
38+
withSizeLabel: valueWithSizeLabel,
39+
size: size || calculatedSize,
40+
precision: valuePrecision,
41+
delimiter,
42+
});
43+
const formattedTotal = formatter({
44+
value: total,
45+
size: size || calculatedSize,
46+
delimiter,
47+
});
48+
49+
return [formattedValue, formattedTotal];
50+
}

0 commit comments

Comments
 (0)