Skip to content
20 changes: 20 additions & 0 deletions src/components/InfoViewer/InfoViewer.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use '../../styles/mixins.scss';

.info-viewer {
--ydb-info-viewer-font-size: var(--g-text-body-2-font-size);
--ydb-info-viewer-line-height: var(--g-text-body-2-line-height);
Expand Down Expand Up @@ -28,6 +30,10 @@

max-width: 100%;
padding-top: 4px;

&:first-child {
padding-top: 0;
}
}

&__label {
Expand Down Expand Up @@ -88,4 +94,18 @@
}
}
}

&_variant_small {
.info-viewer__title {
margin: 0 0 var(--g-spacing-3);

color: var(--g-color-text-primary);
@include mixins.subheader-1-typography();
}

.info-viewer__label {
color: var(--g-color-text-secondary);
@include mixins.body-1-typography();
}
}
}
4 changes: 3 additions & 1 deletion src/components/InfoViewer/InfoViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface InfoViewerProps {
info?: InfoViewerItem[];
dots?: boolean;
size?: 's';
variant?: 'default' | 'small';
className?: string;
multilineLabels?: boolean;
renderEmptyState?: (props?: Pick<InfoViewerProps, 'title' | 'size'>) => React.ReactNode;
Expand All @@ -28,6 +29,7 @@ export const InfoViewer = ({
info,
dots = true,
size,
variant = 'default',
className,
multilineLabels,
renderEmptyState,
Expand All @@ -37,7 +39,7 @@ export const InfoViewer = ({
}

return (
<div className={b({size}, className)}>
<div className={b({size, variant}, className)}>
{title && <div className={b('title')}>{title}</div>}
{info && info.length > 0 ? (
<div className={b('items')}>
Expand Down
10 changes: 5 additions & 5 deletions src/components/MemoryViewer/MemoryViewer.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
$memory-type-colors: (
'AllocatorCachesMemory': var(--g-color-base-utility-medium-hover),
'SharedCacheConsumption': var(--g-color-base-info-medium-hover),
'MemTableConsumption': var(--g-color-base-warning-medium-hover),
'QueryExecutionConsumption': var(--g-color-base-positive-medium-hover),
'Other': var(--g-color-base-generic-medium-hover),
'SharedCacheConsumption': var(--g-color-base-info-medium),
'QueryExecutionConsumption': var(--g-color-base-positive-medium),
'MemTableConsumption': var(--g-color-base-warning-medium),
'AllocatorCachesMemory': var(--g-color-base-danger-medium),
'Other': var(--g-color-base-neutral-medium),
);

@mixin memory-type-color($type) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/MemoryViewer/MemoryViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type {TMemoryStats} from '../../types/api/nodes';
import {formatBytes} from '../../utils/bytesParsers';
import {cn} from '../../utils/cn';
import {GIGABYTE} from '../../utils/constants';
import type {FormatProgressViewerValues} from '../../utils/progress';
import {calculateProgressStatus} from '../../utils/progress';
import {isNumeric} from '../../utils/utils';
import {HoverPopup} from '../HoverPopup/HoverPopup';
import type {FormatProgressViewerValues} from '../ProgressViewer/ProgressViewer';
import {ProgressViewer} from '../ProgressViewer/ProgressViewer';

import {calculateAllocatedMemory, getMemorySegments} from './utils';
Expand Down
3 changes: 2 additions & 1 deletion src/components/MemoryViewer/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"text_usage": "Usage",
"text_soft-limit": "Soft Limit",
"text_hard-limit": "Hard Limit",
"text_other": "Other"
"text_other": "Other",
"text_memory-details": "Memory Details"
}
15 changes: 14 additions & 1 deletion src/components/MemoryViewer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,27 @@ export function getMaybeNumber(value: string | number | undefined): number | und
return isNumeric(value) ? parseFloat(String(value)) : undefined;
}

interface MemorySegment {
export interface MemorySegment {
label: string;
key: string;
value: number;
capacity?: number;
isInfo?: boolean;
}

// Memory segment colors using CSS variables for theme support
export const MEMORY_SEGMENT_COLORS: Record<string, string> = {
SharedCacheConsumption: 'var(--g-color-base-info-medium)',
QueryExecutionConsumption: 'var(--g-color-base-positive-medium)',
MemTableConsumption: 'var(--g-color-base-warning-medium)',
AllocatorCachesMemory: 'var(--g-color-base-danger-medium)',
Other: 'var(--g-color-base-neutral-medium)',
};

export function getMemorySegmentColor(key: string): string {
return MEMORY_SEGMENT_COLORS[key] || MEMORY_SEGMENT_COLORS['Other'];
}

export function getMemorySegments(stats: TMemoryStats, memoryUsage: number): MemorySegment[] {
const segments = [
{
Expand Down
19 changes: 3 additions & 16 deletions src/components/ProgressViewer/ProgressViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {useTheme} from '@gravity-ui/uikit';

import {cn} from '../../utils/cn';
import {formatNumber, roundToPrecision} from '../../utils/dataFormatters/dataFormatters';
import {calculateProgressStatus} from '../../utils/progress';
import {calculateProgressStatus, defaultFormatProgressValues} from '../../utils/progress';
import type {FormatProgressViewerValues} from '../../utils/progress';
import {isNumeric} from '../../utils/utils';

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

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

export type FormatProgressViewerValues = (
value?: number,
capacity?: number,
) => (string | number | undefined)[];

const formatValue = (value?: number) => {
return formatNumber(roundToPrecision(Number(value), 2));
};

const defaultFormatValues: FormatProgressViewerValues = (value, total) => {
return [formatValue(value), formatValue(total)];
};

/*

Props description:
Expand Down Expand Up @@ -56,7 +43,7 @@ export interface ProgressViewerProps {
export function ProgressViewer({
value,
capacity,
formatValues = defaultFormatValues,
formatValues = defaultFormatProgressValues,
percents,
withOverflow,
className,
Expand Down
4 changes: 4 additions & 0 deletions src/components/ProgressViewer/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"value_of_capacity": "{{value}} of {{capacity}}",
"no-data": "No data"
}
7 changes: 7 additions & 0 deletions src/components/ProgressViewer/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {registerKeysets} from '../../../utils/i18n';

import en from './en.json';

const COMPONENT = 'ydb-progress-viewer';

export default registerKeysets(COMPONENT, {en});
25 changes: 25 additions & 0 deletions src/components/ProgressWrapper/ProgressContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {Flex, Text} from '@gravity-ui/uikit';

import {getProgressStyle} from './progressUtils';
import type {ProgressContainerProps} from './types';

export function ProgressContainer({
children,
displayText,
withValue = false,
className,
width,
}: ProgressContainerProps) {
const progressStyle = getProgressStyle(width);

return (
<Flex alignItems="center" gap="2" className={className}>
<div style={progressStyle}>{children}</div>
{withValue && displayText && (
<Text variant="body-1" color="secondary">
{displayText}
</Text>
)}
</Flex>
);
}
10 changes: 10 additions & 0 deletions src/components/ProgressWrapper/ProgressWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {SingleProgress} from './SingleProgress';
import {StackProgress} from './StackProgress';
import type {ProgressWrapperProps} from './types';

export function ProgressWrapper(props: ProgressWrapperProps) {
if ('stack' in props && props.stack) {
return <StackProgress {...props} />;
}
return <SingleProgress {...props} />;
}
54 changes: 54 additions & 0 deletions src/components/ProgressWrapper/SingleProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';

import {Progress} from '@gravity-ui/uikit';

import {defaultFormatProgressValues} from '../../utils/progress';
import {safeParseNumber} from '../../utils/utils';

import {ProgressContainer} from './ProgressContainer';
import i18n from './i18n';
import {
PROGRESS_SIZE,
calculateProgressWidth,
formatDisplayValues,
formatProgressText,
isValidValue,
} from './progressUtils';
import type {ProgressWrapperSingleProps} from './types';

export function SingleProgress({
value,
capacity,
formatValues = defaultFormatProgressValues,
className,
width,
size = PROGRESS_SIZE,
withValue = false,
}: ProgressWrapperSingleProps) {
if (!isValidValue(value)) {
return <div className={className}>{i18n('alert_no-data')}</div>;
}

const numericValue = safeParseNumber(value);
const numericCapacity = safeParseNumber(capacity);
const clampedFillWidth = calculateProgressWidth(numericValue, numericCapacity);

const [valueText, capacityText] = React.useMemo(() => {
return formatDisplayValues(value, capacity, formatValues);
}, [formatValues, value, capacity]);

const displayText = React.useMemo(() => {
return formatProgressText(valueText, capacityText, numericCapacity, i18n);
}, [valueText, capacityText, numericCapacity]);

return (
<ProgressContainer
displayText={displayText}
withValue={withValue}
className={className}
width={width}
>
<Progress value={clampedFillWidth} theme="success" size={size} />
</ProgressContainer>
);
}
67 changes: 67 additions & 0 deletions src/components/ProgressWrapper/StackProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';

import {Progress} from '@gravity-ui/uikit';

import {defaultFormatProgressValues} from '../../utils/progress';
import {safeParseNumber} from '../../utils/utils';
import {getMemorySegmentColor} from '../MemoryViewer/utils';

import {ProgressContainer} from './ProgressContainer';
import i18n from './i18n';
import {
MAX_PERCENTAGE,
PROGRESS_SIZE,
formatDisplayValues,
formatProgressText,
} from './progressUtils';
import type {ProgressWrapperStackProps} from './types';

export function StackProgress({
stack,
totalCapacity,
formatValues = defaultFormatProgressValues,
className,
width,
size = PROGRESS_SIZE,
withValue = false,
}: ProgressWrapperStackProps) {
const displaySegments = stack.filter((segment) => !segment.isInfo && segment.value > 0);

if (displaySegments.length === 0) {
return <div className={className}>{i18n('alert_no-data')}</div>;
}

const totalValue = displaySegments.reduce((sum, segment) => sum + segment.value, 0);
const numericTotalCapacity = safeParseNumber(totalCapacity);
const maxValue = numericTotalCapacity || totalValue;

const stackElements = displaySegments.map((segment) => ({
value: maxValue > 0 ? (segment.value / maxValue) * MAX_PERCENTAGE : 0,
color: getMemorySegmentColor(segment.key),
title: segment.label,
}));

const [totalValueText, totalCapacityText] = React.useMemo(() => {
return formatDisplayValues(totalValue, numericTotalCapacity || totalValue, formatValues);
}, [formatValues, totalValue, numericTotalCapacity]);

const displayText = React.useMemo(() => {
return formatProgressText(
totalValueText,
totalCapacityText,
numericTotalCapacity || 0,
i18n,
);
}, [totalValueText, totalCapacityText, numericTotalCapacity]);

return (
<ProgressContainer
displayText={displayText}
withValue={withValue}
className={className}
width={width}
>
<Progress value={MAX_PERCENTAGE} stack={stackElements} size={size} />
</ProgressContainer>
);
}
4 changes: 4 additions & 0 deletions src/components/ProgressWrapper/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"alert_no-data": "no data",
"context_capacity-usage": "{{value}} of {{capacity}}"
}
11 changes: 11 additions & 0 deletions src/components/ProgressWrapper/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {registerKeysets} from '../../../utils/i18n';

import en from './en.json';

const COMPONENT = 'progress-wrapper';

const keysets = {
en,
};

export default registerKeysets(COMPONENT, keysets);
18 changes: 18 additions & 0 deletions src/components/ProgressWrapper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Main component - public API
export {ProgressWrapper} from './ProgressWrapper';

// Individual components - for direct usage if needed
export {SingleProgress} from './SingleProgress';
export {StackProgress} from './StackProgress';
export {ProgressContainer} from './ProgressContainer';

// Types - for consumers
export type {
ProgressWrapperProps,
ProgressWrapperSingleProps,
ProgressWrapperStackProps,
ProgressContainerProps,
} from './types';

// Utils - for advanced usage
export * from './progressUtils';
Loading
Loading