Skip to content

Commit 7ecf8f3

Browse files
committed
feat: redesign Storage section
1 parent c945a78 commit 7ecf8f3

File tree

22 files changed

+244
-66
lines changed

22 files changed

+244
-66
lines changed

src/components/InfoViewer/InfoViewer.scss

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use '../../styles/mixins.scss';
2+
13
.info-viewer {
24
--ydb-info-viewer-font-size: var(--g-text-body-2-font-size);
35
--ydb-info-viewer-line-height: var(--g-text-body-2-line-height);
@@ -28,6 +30,10 @@
2830

2931
max-width: 100%;
3032
padding-top: 4px;
33+
34+
&:first-child {
35+
padding-top: 0;
36+
}
3137
}
3238

3339
&__label {
@@ -88,4 +94,18 @@
8894
}
8995
}
9096
}
97+
98+
&_variant_small {
99+
.info-viewer__title {
100+
margin: 0 0 var(--g-spacing-3);
101+
102+
color: var(--g-color-text-primary);
103+
@include mixins.subheader-1-typography();
104+
}
105+
106+
.info-viewer__label {
107+
color: var(--g-color-text-secondary);
108+
@include mixins.body-1-typography();
109+
}
110+
}
91111
}

src/components/InfoViewer/InfoViewer.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface InfoViewerProps {
1616
info?: InfoViewerItem[];
1717
dots?: boolean;
1818
size?: 's';
19+
variant?: 'default' | 'small';
1920
className?: string;
2021
multilineLabels?: boolean;
2122
renderEmptyState?: (props?: Pick<InfoViewerProps, 'title' | 'size'>) => React.ReactNode;
@@ -28,6 +29,7 @@ export const InfoViewer = ({
2829
info,
2930
dots = true,
3031
size,
32+
variant = 'default',
3133
className,
3234
multilineLabels,
3335
renderEmptyState,
@@ -37,7 +39,7 @@ export const InfoViewer = ({
3739
}
3840

3941
return (
40-
<div className={b({size}, className)}>
42+
<div className={b({size, variant}, className)}>
4143
{title && <div className={b('title')}>{title}</div>}
4244
{info && info.length > 0 ? (
4345
<div className={b('items')}>

src/components/MemoryViewer/MemoryViewer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import type {TMemoryStats} from '../../types/api/nodes';
44
import {formatBytes} from '../../utils/bytesParsers';
55
import {cn} from '../../utils/cn';
66
import {GIGABYTE} from '../../utils/constants';
7+
import type {FormatProgressViewerValues} from '../../utils/progress';
78
import {calculateProgressStatus} from '../../utils/progress';
89
import {isNumeric} from '../../utils/utils';
910
import {HoverPopup} from '../HoverPopup/HoverPopup';
10-
import type {FormatProgressViewerValues} from '../ProgressViewer/ProgressViewer';
1111
import {ProgressViewer} from '../ProgressViewer/ProgressViewer';
1212

1313
import {calculateAllocatedMemory, getMemorySegments} from './utils';

src/components/ProgressViewer/ProgressViewer.tsx

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {useTheme} from '@gravity-ui/uikit';
22

33
import {cn} from '../../utils/cn';
4-
import {formatNumber, roundToPrecision} from '../../utils/dataFormatters/dataFormatters';
5-
import {calculateProgressStatus} from '../../utils/progress';
4+
import {calculateProgressStatus, defaultFormatProgressValues} from '../../utils/progress';
5+
import type {FormatProgressViewerValues} from '../../utils/progress';
66
import {isNumeric} from '../../utils/utils';
77

88
import './ProgressViewer.scss';
@@ -11,19 +11,6 @@ const b = cn('progress-viewer');
1111

1212
type ProgressViewerSize = 'xs' | 's' | 'ns' | 'm' | 'n' | 'l' | 'head';
1313

14-
export type FormatProgressViewerValues = (
15-
value?: number,
16-
capacity?: number,
17-
) => (string | number | undefined)[];
18-
19-
const formatValue = (value?: number) => {
20-
return formatNumber(roundToPrecision(Number(value), 2));
21-
};
22-
23-
const defaultFormatValues: FormatProgressViewerValues = (value, total) => {
24-
return [formatValue(value), formatValue(total)];
25-
};
26-
2714
/*
2815
2916
Props description:
@@ -56,7 +43,7 @@ export interface ProgressViewerProps {
5643
export function ProgressViewer({
5744
value,
5845
capacity,
59-
formatValues = defaultFormatValues,
46+
formatValues = defaultFormatProgressValues,
6047
percents,
6148
withOverflow,
6249
className,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"no-data": "No data"
3+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {registerKeysets} from '../../../utils/i18n';
2+
3+
import en from './en.json';
4+
5+
const COMPONENT = 'ydb-progress-viewer';
6+
7+
export default registerKeysets(COMPONENT, {en});

src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/useTenantCpuQueryParams.ts

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {StringParam, useQueryParams} from 'use-query-params';
22

33
import {
4-
TENANT_CPU_NODES_MODE_IDS,
5-
TENANT_CPU_TABS_IDS,
6-
} from '../../../../../store/reducers/tenant/constants';
4+
tenantCpuTabSchema,
5+
tenantNodesModeSchema,
6+
} from '../../../../../store/reducers/tenant/types';
77
import type {TenantCpuTab, TenantNodesMode} from '../../../../../store/reducers/tenant/types';
88

99
export function useTenantCpuQueryParams() {
@@ -12,27 +12,8 @@ export function useTenantCpuQueryParams() {
1212
nodesMode: StringParam,
1313
});
1414

15-
// Parse and validate cpuTab with fallback to nodes
16-
const cpuTab: TenantCpuTab = (() => {
17-
if (!queryParams.cpuTab) {
18-
return TENANT_CPU_TABS_IDS.nodes;
19-
}
20-
const validTabs = Object.values(TENANT_CPU_TABS_IDS) as string[];
21-
return validTabs.includes(queryParams.cpuTab)
22-
? (queryParams.cpuTab as TenantCpuTab)
23-
: TENANT_CPU_TABS_IDS.nodes;
24-
})();
25-
26-
// Parse and validate nodesMode with fallback to load
27-
const nodesMode: TenantNodesMode = (() => {
28-
if (!queryParams.nodesMode) {
29-
return TENANT_CPU_NODES_MODE_IDS.load;
30-
}
31-
const validModes = Object.values(TENANT_CPU_NODES_MODE_IDS) as string[];
32-
return validModes.includes(queryParams.nodesMode)
33-
? (queryParams.nodesMode as TenantNodesMode)
34-
: TENANT_CPU_NODES_MODE_IDS.load;
35-
})();
15+
const cpuTab: TenantCpuTab = tenantCpuTabSchema.parse(queryParams.cpuTab);
16+
const nodesMode: TenantNodesMode = tenantNodesModeSchema.parse(queryParams.nodesMode);
3617

3718
const handleCpuTabChange = (value: TenantCpuTab) => {
3819
setQueryParams({cpuTab: value}, 'replaceIn');

src/containers/Tenant/Diagnostics/TenantOverview/TenantDashboard/TenantDashboard.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.ydb-tenant-dashboard {
22
width: var(--diagnostics-section-table-width);
3-
margin-bottom: var(--diagnostics-section-margin);
3+
margin-bottom: var(--g-spacing-4);
44

55
&__charts {
66
display: flex;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from 'react';
2+
3+
import {Flex, Progress, Text} from '@gravity-ui/uikit';
4+
5+
import {defaultFormatProgressValues} from '../../../../../utils/progress';
6+
import type {FormatProgressViewerValues} from '../../../../../utils/progress';
7+
import {isNumeric, safeParseNumber} from '../../../../../utils/utils';
8+
9+
import {DEFAULT_PROGRESS_WIDTH, MAX_PERCENTAGE, MIN_PERCENTAGE, PROGRESS_SIZE} from './constants';
10+
import i18n from './i18n';
11+
12+
interface ProgressWrapperProps {
13+
value?: number | string;
14+
capacity?: number | string;
15+
formatValues?: FormatProgressViewerValues;
16+
className?: string;
17+
width?: number;
18+
}
19+
20+
const isValidValue = (val?: number | string): boolean =>
21+
isNumeric(val) && safeParseNumber(val) >= 0;
22+
23+
export function ProgressWrapper({
24+
value,
25+
capacity,
26+
formatValues = defaultFormatProgressValues,
27+
className,
28+
width = DEFAULT_PROGRESS_WIDTH,
29+
}: ProgressWrapperProps) {
30+
if (!isValidValue(value)) {
31+
return <div className={className}>{i18n('alert_no-data')}</div>;
32+
}
33+
34+
const numericValue = safeParseNumber(value);
35+
const numericCapacity = safeParseNumber(capacity);
36+
37+
const rawPercentage =
38+
numericCapacity > 0
39+
? Math.floor((numericValue / numericCapacity) * MAX_PERCENTAGE)
40+
: MAX_PERCENTAGE;
41+
const fillWidth = Math.max(MIN_PERCENTAGE, rawPercentage);
42+
const clampedFillWidth = Math.min(fillWidth, MAX_PERCENTAGE);
43+
44+
const [valueText, capacityText] = React.useMemo(() => {
45+
return formatValues(Number(value), Number(capacity));
46+
}, [formatValues, value, capacity]);
47+
48+
const displayText = React.useMemo(() => {
49+
if (numericCapacity <= 0) {
50+
return String(valueText);
51+
}
52+
return i18n('context_capacity-usage', {value: valueText, capacity: capacityText});
53+
}, [valueText, capacityText, numericCapacity]);
54+
55+
const validatedWidth = Math.max(0, width);
56+
57+
return (
58+
<Flex alignItems="center" gap="2" className={className}>
59+
<div style={{width: `${validatedWidth}px`}}>
60+
<Progress value={clampedFillWidth} theme="success" size={PROGRESS_SIZE} />
61+
</div>
62+
<Text variant="body-1" color="secondary">
63+
{displayText}
64+
</Text>
65+
</Flex>
66+
);
67+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.tenant-storage {
2+
&__tabs-container {
3+
margin-top: var(--g-spacing-3);
4+
}
5+
6+
&__tab-content {
7+
margin-top: var(--g-spacing-3);
8+
}
9+
}

0 commit comments

Comments
 (0)