Skip to content

Commit 437a81c

Browse files
authored
feat: redesign Memory section (#2627)
1 parent 151d766 commit 437a81c

27 files changed

+584
-137
lines changed

package-lock.json

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@bem-react/classname": "^1.6.0",
1414
"@ebay/nice-modal-react": "^1.2.13",
1515
"@gravity-ui/axios-wrapper": "^1.5.1",
16-
"@gravity-ui/chartkit": "^7.0.1",
16+
"@gravity-ui/chartkit": "^7.1.0",
1717
"@gravity-ui/components": "^4.4.0",
1818
"@gravity-ui/date-components": "^3.2.3",
1919
"@gravity-ui/date-utils": "^2.5.6",

src/components/MemoryViewer/MemoryViewer.scss

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
$memory-type-colors: (
2-
'AllocatorCachesMemory': var(--g-color-base-utility-medium-hover),
3-
'SharedCacheConsumption': var(--g-color-base-info-medium-hover),
4-
'MemTableConsumption': var(--g-color-base-warning-medium-hover),
5-
'QueryExecutionConsumption': var(--g-color-base-positive-medium-hover),
6-
'Other': var(--g-color-base-generic-medium-hover),
2+
'AllocatorCachesMemory': var(--g-color-base-danger-medium),
3+
'SharedCacheConsumption': var(--g-color-base-info-medium),
4+
'MemTableConsumption': var(--g-color-base-warning-medium),
5+
'QueryExecutionConsumption': var(--g-color-base-positive-medium),
6+
'Other': var(--g-color-base-neutral-medium),
77
);
88

99
@mixin memory-type-color($type) {
@@ -31,8 +31,6 @@ $memory-type-colors: (
3131
}
3232

3333
&__container {
34-
display: flex;
35-
3634
padding: 2px 0;
3735
}
3836

@@ -93,10 +91,4 @@ $memory-type-colors: (
9391
}
9492
}
9593
}
96-
97-
&__text {
98-
display: flex;
99-
justify-content: center;
100-
align-items: center;
101-
}
10294
}

src/components/MemoryViewer/MemoryViewer.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DefinitionList, useTheme} from '@gravity-ui/uikit';
1+
import {DefinitionList, Flex, useTheme} from '@gravity-ui/uikit';
22

33
import type {TMemoryStats} from '../../types/api/nodes';
44
import {formatBytes} from '../../utils/bytesParsers';
@@ -107,10 +107,10 @@ export function MemoryViewer({
107107
<DefinitionList.Item
108108
key={label}
109109
name={
110-
<div className={b('container')}>
110+
<Flex alignItems="center" gap="1" className={b('container')}>
111111
<div className={b('legend', {type: key})}></div>
112112
<div className={b('name')}>{label}</div>
113-
</div>
113+
</Flex>
114114
}
115115
>
116116
{segmentCapacity ? (
@@ -161,7 +161,9 @@ export function MemoryViewer({
161161
/>
162162
);
163163
})}
164-
<div className={b('text')}>{renderContent()}</div>
164+
<Flex justifyContent="center" alignItems="center" className={b('text')}>
165+
{renderContent()}
166+
</Flex>
165167
</div>
166168
</div>
167169
</HoverPopup>

src/components/MemoryViewer/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
"text_usage": "Usage",
88
"text_soft-limit": "Soft Limit",
99
"text_hard-limit": "Hard Limit",
10-
"text_other": "Other"
10+
"text_other": "Other",
11+
"text_memory-details": "Memory Details"
1112
}

src/components/MemoryViewer/utils.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,31 @@ export function calculateAllocatedMemory(stats: TMemoryStats) {
99
return String(allocatedMemory + allocatorCaches);
1010
}
1111

12-
export function getMaybeNumber(value: string | number | undefined): number | undefined {
12+
function getMaybeNumber(value: string | number | undefined): number | undefined {
1313
return isNumeric(value) ? parseFloat(String(value)) : undefined;
1414
}
1515

16-
interface MemorySegment {
16+
export interface MemorySegment {
1717
label: string;
1818
key: string;
1919
value: number;
2020
capacity?: number;
2121
isInfo?: boolean;
2222
}
2323

24+
// Memory segment colors using CSS variables for theme support
25+
export const MEMORY_SEGMENT_COLORS: Record<string, string> = {
26+
AllocatorCachesMemory: 'var(--g-color-base-danger-medium)',
27+
SharedCacheConsumption: 'var(--g-color-base-info-medium)',
28+
MemTableConsumption: 'var(--g-color-base-warning-medium)',
29+
QueryExecutionConsumption: 'var(--g-color-base-positive-medium)',
30+
Other: 'var(--g-color-base-neutral-medium)',
31+
};
32+
33+
export function getMemorySegmentColor(key: string): string {
34+
return MEMORY_SEGMENT_COLORS[key] || MEMORY_SEGMENT_COLORS['Other'];
35+
}
36+
2437
export function getMemorySegments(stats: TMemoryStats, memoryUsage: number): MemorySegment[] {
2538
const segments = [
2639
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {Flex, Text} from '@gravity-ui/uikit';
2+
3+
import {getProgressStyle} from './progressUtils';
4+
import type {ProgressContainerProps} from './types';
5+
6+
export function ProgressContainer({
7+
children,
8+
displayText,
9+
withCapacityUsage = false,
10+
className,
11+
width,
12+
}: ProgressContainerProps) {
13+
const progressStyle = getProgressStyle(width);
14+
15+
return (
16+
<Flex alignItems="center" gap="2" className={className}>
17+
<div style={progressStyle}>{children}</div>
18+
{withCapacityUsage && displayText && (
19+
<Text variant="body-1" color="secondary">
20+
{displayText}
21+
</Text>
22+
)}
23+
</Flex>
24+
);
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {SingleProgress} from './SingleProgress';
2+
import {StackProgress} from './StackProgress';
3+
import type {ProgressWrapperProps} from './types';
4+
5+
export function ProgressWrapper(props: ProgressWrapperProps) {
6+
if ('stack' in props && props.stack) {
7+
return <StackProgress {...props} />;
8+
}
9+
return <SingleProgress {...props} />;
10+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
3+
import {Progress} from '@gravity-ui/uikit';
4+
5+
import {defaultFormatProgressValues} from '../../utils/progress';
6+
import {safeParseNumber} from '../../utils/utils';
7+
8+
import {ProgressContainer} from './ProgressContainer';
9+
import i18n from './i18n';
10+
import {
11+
PROGRESS_SIZE,
12+
calculateProgressWidth,
13+
formatDisplayValues,
14+
formatProgressText,
15+
isValidValue,
16+
} from './progressUtils';
17+
import type {ProgressWrapperSingleProps} from './types';
18+
19+
export function SingleProgress({
20+
value,
21+
capacity,
22+
formatValues = defaultFormatProgressValues,
23+
className,
24+
width,
25+
size = PROGRESS_SIZE,
26+
withCapacityUsage = false,
27+
}: ProgressWrapperSingleProps) {
28+
if (!isValidValue(value)) {
29+
return <div className={className}>{i18n('alert_no-data')}</div>;
30+
}
31+
32+
const numericValue = safeParseNumber(value);
33+
const numericCapacity = safeParseNumber(capacity);
34+
const clampedFillWidth = calculateProgressWidth(numericValue, numericCapacity);
35+
36+
const [valueText, capacityText] = React.useMemo(() => {
37+
return formatDisplayValues(value, capacity, formatValues);
38+
}, [formatValues, value, capacity]);
39+
40+
const displayText = React.useMemo(() => {
41+
return formatProgressText(valueText, capacityText, numericCapacity);
42+
}, [valueText, capacityText, numericCapacity]);
43+
44+
return (
45+
<ProgressContainer
46+
displayText={displayText}
47+
withCapacityUsage={withCapacityUsage}
48+
className={className}
49+
width={width}
50+
>
51+
<Progress value={clampedFillWidth} theme="success" size={size} />
52+
</ProgressContainer>
53+
);
54+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React from 'react';
2+
3+
import {Progress} from '@gravity-ui/uikit';
4+
5+
import {defaultFormatProgressValues} from '../../utils/progress';
6+
import {safeParseNumber} from '../../utils/utils';
7+
import {getMemorySegmentColor} from '../MemoryViewer/utils';
8+
9+
import {ProgressContainer} from './ProgressContainer';
10+
import i18n from './i18n';
11+
import {
12+
MAX_PERCENTAGE,
13+
PROGRESS_SIZE,
14+
formatDisplayValues,
15+
formatProgressText,
16+
} from './progressUtils';
17+
import type {ProgressWrapperStackProps} from './types';
18+
19+
export function StackProgress({
20+
stack,
21+
totalCapacity,
22+
formatValues = defaultFormatProgressValues,
23+
className,
24+
width,
25+
size = PROGRESS_SIZE,
26+
withCapacityUsage = false,
27+
}: ProgressWrapperStackProps) {
28+
const displaySegments = React.useMemo(() => {
29+
return stack.filter((segment) => !segment.isInfo && segment.value > 0);
30+
}, [stack]);
31+
32+
if (displaySegments.length === 0) {
33+
return <div className={className}>{i18n('alert_no-data')}</div>;
34+
}
35+
36+
const totalValue = React.useMemo(() => {
37+
return displaySegments.reduce((sum, segment) => sum + segment.value, 0);
38+
}, [displaySegments]);
39+
40+
const numericTotalCapacity = React.useMemo(() => {
41+
return safeParseNumber(totalCapacity);
42+
}, [totalCapacity]);
43+
44+
const maxValue = numericTotalCapacity || totalValue;
45+
46+
const stackElements = React.useMemo(() => {
47+
return displaySegments.map((segment) => ({
48+
value: maxValue > 0 ? (segment.value / maxValue) * MAX_PERCENTAGE : 0,
49+
color: getMemorySegmentColor(segment.key),
50+
title: segment.label,
51+
}));
52+
}, [displaySegments, maxValue]);
53+
54+
const [totalValueText, totalCapacityText] = React.useMemo(() => {
55+
return formatDisplayValues(totalValue, numericTotalCapacity || totalValue, formatValues);
56+
}, [formatValues, totalValue, numericTotalCapacity]);
57+
58+
const displayText = React.useMemo(() => {
59+
return formatProgressText(totalValueText, totalCapacityText, numericTotalCapacity || 0);
60+
}, [totalValueText, totalCapacityText, numericTotalCapacity]);
61+
62+
return (
63+
<ProgressContainer
64+
displayText={displayText}
65+
withCapacityUsage={withCapacityUsage}
66+
className={className}
67+
width={width}
68+
>
69+
<Progress value={MAX_PERCENTAGE} stack={stackElements} size={size} />
70+
</ProgressContainer>
71+
);
72+
}

0 commit comments

Comments
 (0)