From c91b5736eaf47504990b3170971e24356247f1f7 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 18:24:45 +0300 Subject: [PATCH 01/11] feat: add partitions progress bar to table info --- .../PartitionsProgress.scss | 50 ++++++ .../PartitionsProgress/PartitionsProgress.tsx | 159 ++++++++++++++++++ .../TableInfo/PartitionsProgress/helpers.ts | 108 ++++++++++++ .../TableInfo/PartitionsProgress/i18n/en.json | 10 ++ .../PartitionsProgress/i18n/index.ts | 7 + .../Overview/TableInfo/TableInfo.scss | 5 + .../Overview/TableInfo/TableInfo.tsx | 18 +- .../Overview/TableInfo/i18n/en.json | 5 +- .../Overview/TableInfo/prepareTableInfo.tsx | 40 ++++- 9 files changed, 394 insertions(+), 8 deletions(-) create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/en.json create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/index.ts diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss new file mode 100644 index 0000000000..740f0e49a7 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss @@ -0,0 +1,50 @@ +.ydb-partitions-progress { + &__segment { + display: flex; + flex-basis: 0; + + &_left, + &_right { + min-width: 20px; + } + + &_main { + min-width: 70px; + } + } + + &__segment-bar { + &_left, + &_right { + --g-progress-filled-background-color: var(--g-color-base-danger-heavy); + } + + &_main { + --g-progress-filled-background-color: var(--g-color-base-info-heavy); + --g-progress-empty-background-color: var(--g-color-base-info-light); + } + } + + &__segment-labels { + display: flex; + + &_left { + justify-content: flex-start; + } + + &_right { + justify-content: flex-end; + } + + &_main { + justify-content: space-between; + } + } + + &__segment-touched { + padding: var(--g-spacing-2); + + font-size: var(--g-text-body-2-font-size); + line-height: var(--g-text-body-2-line-height); + } +} diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx new file mode 100644 index 0000000000..67ad2ce3bd --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -0,0 +1,159 @@ +import {Flex, Popover, Progress, Text} from '@gravity-ui/uikit'; +import {isNil} from 'lodash'; + +import {cn} from '../../../../../../utils/cn'; + +import {calcPartitionsProgress, getPartitionsLabel} from './helpers'; +import i18n from './i18n'; + +import './PartitionsProgress.scss'; + +const b = cn('ydb-partitions-progress'); + +interface PartitionsProgressProps { + minPartitions: number; + maxPartitions?: number; + partitionsCount: number; + className?: string; +} + +type SegmentPosition = 'left' | 'main' | 'right'; + +const SEGMENT_MODS: Record> = { + left: {left: true}, + main: {main: true}, + right: {right: true}, +}; + +const FULL_FILL_VALUE = 100; + +interface SegmentProgressBarProps { + position: SegmentPosition; + value: number; + tooltip: string; + theme?: 'default' | 'danger'; +} + +const SegmentProgressBar = ({ + position, + value, + tooltip, + theme = 'default', +}: SegmentProgressBarProps) => ( + +
+ +
+
+); + +export const PartitionsProgress = ({ + minPartitions, + maxPartitions, + partitionsCount, + className, +}: PartitionsProgressProps) => { + const { + min, + max, + partitionsBelowMin, + partitionsAboveMax, + isBelowMin, + isAboveMax, + leftSegmentUnits, + mainSegmentUnits, + rightSegmentUnits, + mainProgressValue, + } = calcPartitionsProgress(minPartitions, maxPartitions, partitionsCount); + + const partitionsLabel = getPartitionsLabel(partitionsCount); + + const belowLimitTooltip = i18n('tooltip_partitions-below-limit', { + count: partitionsCount, + diff: partitionsBelowMin, + partitions: partitionsLabel, + }); + + const aboveLimitTooltip = i18n('tooltip_partitions-above-limit', { + count: partitionsCount, + diff: partitionsAboveMax, + partitions: partitionsLabel, + }); + + const currentTooltip = i18n('tooltip_partitions-current', { + count: partitionsCount, + partitions: partitionsLabel, + }); + + const maxLabel = isNil(max) ? i18n('value_no-limit') : max; + + return ( + + {isBelowMin && ( + + + +
+ + {partitionsCount} + +
+
+ )} + + + + +
+ + {min} + + + {maxLabel} + +
+
+ + {isAboveMax && ( + + + +
+ + {partitionsCount} + +
+
+ )} +
+ ); +}; diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts new file mode 100644 index 0000000000..28439ad8cc --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts @@ -0,0 +1,108 @@ +import {isNil} from 'lodash'; + +import i18n from './i18n'; + +export interface PartitionsProgressCalcResult { + min: number; + max?: number; + + partitionsBelowMin: number; + partitionsAboveMax: number; + + isBelowMin: boolean; + isAboveMax: boolean; + + leftSegmentUnits: number; + mainSegmentUnits: number; + rightSegmentUnits: number; + + mainProgressValue: number; +} + +export function calcPartitionsProgress( + minPartitions: number, + maxPartitions: number | undefined, + partitionsCount: number, +): PartitionsProgressCalcResult { + const min = minPartitions; + + const hasMaxLimit = !isNil(maxPartitions); + + if (!hasMaxLimit) { + const partitionsBelowMin = Math.max(0, min - partitionsCount); + const partitionsAboveMax = 0; + const isBelowMin = partitionsBelowMin > 0; + const isAboveMax = false; + + // When max limit is not provided, reserve a fixed 20% of the total width + // for the "below min" segment (1:4 ratio between warning and main segments). + const leftSegmentUnits = isBelowMin ? 1 : 0; + const mainSegmentUnits = isBelowMin ? 4 : 1; + const rightSegmentUnits = 0; + + const mainProgressValue = partitionsCount < min ? 0 : 100; + + return { + min, + max: undefined, + + partitionsBelowMin, + partitionsAboveMax, + + isBelowMin, + isAboveMax, + + leftSegmentUnits, + mainSegmentUnits, + rightSegmentUnits, + + mainProgressValue, + }; + } + + const max = Math.max(maxPartitions as number, minPartitions); + + const range = Math.max(0, max - min); + + const partitionsBelowMin = Math.max(0, min - partitionsCount); + const partitionsAboveMax = Math.max(0, partitionsCount - max); + + const isBelowMin = partitionsBelowMin > 0; + const isAboveMax = partitionsAboveMax > 0; + + const mainSegmentUnits = range || 1; + + let mainProgressValue = 0; + if (range > 0) { + if (partitionsCount <= min) { + mainProgressValue = 0; + } else if (partitionsCount >= max) { + mainProgressValue = 100; + } else { + mainProgressValue = ((partitionsCount - min) / range) * 100; + } + } + + const leftSegmentUnits = isBelowMin ? partitionsBelowMin : 0; + const rightSegmentUnits = isAboveMax ? partitionsAboveMax : 0; + + return { + min, + max, + + partitionsBelowMin, + partitionsAboveMax, + + isBelowMin, + isAboveMax, + + leftSegmentUnits, + mainSegmentUnits, + rightSegmentUnits, + + mainProgressValue, + }; +} + +export const getPartitionsLabel = (count: number) => + count === 1 ? i18n('value_partition-one') : i18n('value_partition-many'); diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/en.json b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/en.json new file mode 100644 index 0000000000..ab452650af --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/en.json @@ -0,0 +1,10 @@ +{ + "tooltip_partitions-current": "{{count}} {{partitions}}", + "tooltip_partitions-below-limit": "{{count}} {{partitions}}. {{diff}} less than the limit", + "tooltip_partitions-above-limit": "{{count}} {{partitions}}. {{diff}} over the limit", + + "value_partition-one": "partition", + "value_partition-many": "partitions", + + "value_no-limit": "No limit" +} diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/index.ts b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/index.ts new file mode 100644 index 0000000000..0062f51ab4 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/i18n/index.ts @@ -0,0 +1,7 @@ +import {registerKeysets} from '../../../../../../../utils/i18n'; + +import en from './en.json'; + +const COMPONENT = 'partitions-progress'; + +export default registerKeysets(COMPONENT, {en}); diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss index 4f787845b4..811f1af5b2 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss @@ -5,6 +5,11 @@ @include mixins.info-viewer-title(); } + &__progress-bar { + max-width: 656px; + padding: var(--g-spacing-3) 0 var(--g-spacing-4); + } + &__row { display: flex; flex-wrap: wrap; diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx index 74eaf96f84..140c86b42c 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx @@ -3,8 +3,8 @@ import React from 'react'; import {InfoViewer} from '../../../../../components/InfoViewer'; import type {EPathType, TEvDescribeSchemeResult} from '../../../../../types/api/schema'; import {cn} from '../../../../../utils/cn'; -import {EntityTitle} from '../../../EntityTitle/EntityTitle'; +import {PartitionsProgress} from './PartitionsProgress/PartitionsProgress'; import i18n from './i18n'; import {prepareTableInfo} from './prepareTableInfo'; @@ -18,22 +18,30 @@ interface TableInfoProps { } export const TableInfo = ({data, type}: TableInfoProps) => { - const title = ; - const { generalInfo, tableStatsInfo, tabletMetricsInfo = [], partitionConfigInfo = [], + partitionProgressConfig, } = React.useMemo(() => prepareTableInfo(data, type), [data, type]); return (
+
{i18n('title')}
+ {partitionProgressConfig && ( +
+ +
+ )}
{title}
} + renderEmptyState={() =>
{i18n('title')}
} />
{tableStatsInfo ? ( diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json b/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json index e449db46b7..8de7d5119f 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json @@ -1,6 +1,7 @@ { - "tableStats": "Table Stats", - "tabletMetrics": "Tablet Metrics", + "title": "Partitioning", + "tableStats": "Stats", + "tabletMetrics": "Metrics", "partitionConfig": "Partition Config", "label.ttl": "TTL for rows", diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx index b96e78fef9..2d7f80374b 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx @@ -15,6 +15,7 @@ import type { TColumnTableDescription, TEvDescribeSchemeResult, TPartitionConfig, + TPersQueueGroupDescription, TTTLSettings, } from '../../../../../types/api/schema'; import {EPathType} from '../../../../../types/api/schema'; @@ -139,6 +140,31 @@ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings? return generalTableInfo; }; +type PartitionProgressConfig = { + minPartitions: number; + maxPartitions?: number; + partitionsCount: number; +}; + +const preparePartitionProgressConfig = ( + PartitionConfig: TPartitionConfig, + PersQueueGroup?: TPersQueueGroupDescription, +): PartitionProgressConfig => { + const {PartitioningPolicy} = PartitionConfig; + + // We are convinced, there is always at least one partition; + // fallback and clamp to 1 if value is missing. + const minPartitions = Math.max(1, PartitioningPolicy?.MinPartitionsCount ?? 1); + const maxPartitions = PartitioningPolicy?.MaxPartitionsCount; + const partitionsCount = Math.max(1, PersQueueGroup?.Partitions?.length ?? 1); + + return { + minPartitions, + maxPartitions, + partitionsCount, + }; +}; + /** Prepares data for Table, ColumnTable and ColumnStore */ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathType) => { if (!data) { @@ -152,6 +178,7 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathTyp TabletMetrics = {}, Table: {PartitionConfig = {}, TTLSettings} = {}, ColumnTableDescription = {}, + PersQueueGroup, } = PathDescription; const { @@ -181,10 +208,15 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathTyp const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig; let generalInfo: InfoViewerItem[] = []; + let partitionProgressConfig: PartitionProgressConfig | undefined; switch (type) { case EPathType.EPathTypeTable: { generalInfo = prepareTableGeneralInfo(PartitionConfig, TTLSettings); + partitionProgressConfig = preparePartitionProgressConfig( + PartitionConfig, + PersQueueGroup, + ); break; } case EPathType.EPathTypeColumnTable: { @@ -252,5 +284,11 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathTyp ); } - return {generalInfo, tableStatsInfo, tabletMetricsInfo, partitionConfigInfo}; + return { + generalInfo, + tableStatsInfo, + tabletMetricsInfo, + partitionConfigInfo, + partitionProgressConfig, + }; }; From f121ed59c50b6c71983a2d29526d7333a5a244ae Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 18:29:33 +0300 Subject: [PATCH 02/11] Fix bugs --- .../PartitionsProgress/PartitionsProgress.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx index 67ad2ce3bd..efd2852288 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -31,18 +31,12 @@ interface SegmentProgressBarProps { position: SegmentPosition; value: number; tooltip: string; - theme?: 'default' | 'danger'; } -const SegmentProgressBar = ({ - position, - value, - tooltip, - theme = 'default', -}: SegmentProgressBarProps) => ( +const SegmentProgressBar = ({position, value, tooltip}: SegmentProgressBarProps) => (
- +
); @@ -100,7 +94,6 @@ export const PartitionsProgress = ({ position="left" value={FULL_FILL_VALUE} tooltip={belowLimitTooltip} - theme="danger" />
@@ -144,7 +137,6 @@ export const PartitionsProgress = ({ position="right" value={FULL_FILL_VALUE} tooltip={aboveLimitTooltip} - theme="danger" />
From ae31b8aef65d73d423991f7485ad46923f758cc3 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 18:41:11 +0300 Subject: [PATCH 03/11] Fix bugs --- .../Overview/TableInfo/prepareTableInfo.tsx | 10 +++++----- src/types/api/schema/schema.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx index 2d7f80374b..6fcce56516 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx @@ -15,8 +15,8 @@ import type { TColumnTableDescription, TEvDescribeSchemeResult, TPartitionConfig, - TPersQueueGroupDescription, TTTLSettings, + TTablePartition, } from '../../../../../types/api/schema'; import {EPathType} from '../../../../../types/api/schema'; import {valueIsDefined} from '../../../../../utils'; @@ -148,7 +148,7 @@ type PartitionProgressConfig = { const preparePartitionProgressConfig = ( PartitionConfig: TPartitionConfig, - PersQueueGroup?: TPersQueueGroupDescription, + TablePartitions?: TTablePartition[], ): PartitionProgressConfig => { const {PartitioningPolicy} = PartitionConfig; @@ -156,7 +156,7 @@ const preparePartitionProgressConfig = ( // fallback and clamp to 1 if value is missing. const minPartitions = Math.max(1, PartitioningPolicy?.MinPartitionsCount ?? 1); const maxPartitions = PartitioningPolicy?.MaxPartitionsCount; - const partitionsCount = Math.max(1, PersQueueGroup?.Partitions?.length ?? 1); + const partitionsCount = TablePartitions?.length ?? 1; return { minPartitions, @@ -174,11 +174,11 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathTyp const {PathDescription = {}} = data; const { + TablePartitions, TableStats = {}, TabletMetrics = {}, Table: {PartitionConfig = {}, TTLSettings} = {}, ColumnTableDescription = {}, - PersQueueGroup, } = PathDescription; const { @@ -215,7 +215,7 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult, type?: EPathTyp generalInfo = prepareTableGeneralInfo(PartitionConfig, TTLSettings); partitionProgressConfig = preparePartitionProgressConfig( PartitionConfig, - PersQueueGroup, + TablePartitions, ); break; } diff --git a/src/types/api/schema/schema.ts b/src/types/api/schema/schema.ts index 319268cc69..0ba521918b 100644 --- a/src/types/api/schema/schema.ts +++ b/src/types/api/schema/schema.ts @@ -334,7 +334,7 @@ interface TPathVersion { GeneralVersion?: string; } -interface TTablePartition { +export interface TTablePartition { /** bytes */ EndOfRangeKeyPrefix?: unknown; IsPoint?: boolean; From b3414be271fd32704b05288b724fa0e8abc6faad Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 18:57:39 +0300 Subject: [PATCH 04/11] Fix bugs --- .../Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx | 7 ++++++- .../Diagnostics/Overview/TableInfo/prepareTableInfo.tsx | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx index 140c86b42c..1f53155790 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx @@ -26,10 +26,15 @@ export const TableInfo = ({data, type}: TableInfoProps) => { partitionProgressConfig, } = React.useMemo(() => prepareTableInfo(data, type), [data, type]); + // Feature flag: show partitions progress only if WINDOW_SHOW_TABLE_SETTINGS is truthy + const isPartitionsProgressEnabled = Boolean( + (window as unknown as {WINDOW_SHOW_TABLE_SETTINGS?: unknown}).WINDOW_SHOW_TABLE_SETTINGS, + ); + return (
{i18n('title')}
- {partitionProgressConfig && ( + {isPartitionsProgressEnabled && partitionProgressConfig && (
Date: Wed, 10 Dec 2025 19:00:56 +0300 Subject: [PATCH 05/11] Fix bugs --- .../Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss index 811f1af5b2..b9255b1235 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss @@ -2,6 +2,7 @@ .ydb-diagnostics-table-info { &__title { + margin-top: 0; @include mixins.info-viewer-title(); } From 205afb91c5fd3670fcff4d98088dca7da8261ca4 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 19:16:11 +0300 Subject: [PATCH 06/11] Fix bugs --- .../Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss index b9255b1235..5774ba225e 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.scss @@ -2,8 +2,10 @@ .ydb-diagnostics-table-info { &__title { - margin-top: 0; - @include mixins.info-viewer-title(); + margin-bottom: 10px; + + font-weight: 600; + @include mixins.body-2-typography(); } &__progress-bar { From 5ff0661df4b6f83349c27141e93212f0fee72ac7 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 19:52:21 +0300 Subject: [PATCH 07/11] Fix bugs --- .../PartitionsProgress/PartitionsProgress.tsx | 118 +++++++++--------- .../TableInfo/PartitionsProgress/helpers.ts | 5 +- .../Overview/TableInfo/TableInfo.tsx | 2 +- 3 files changed, 60 insertions(+), 65 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx index efd2852288..eb68bdd14d 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -25,20 +25,17 @@ const SEGMENT_MODS: Record> = { right: {right: true}, }; -const FULL_FILL_VALUE = 100; +export const FULL_FILL_VALUE = 100; interface SegmentProgressBarProps { position: SegmentPosition; value: number; - tooltip: string; } -const SegmentProgressBar = ({position, value, tooltip}: SegmentProgressBarProps) => ( - -
- -
-
+const SegmentProgressBar = ({position, value}: SegmentProgressBarProps) => ( +
+ +
); export const PartitionsProgress = ({ @@ -81,71 +78,68 @@ export const PartitionsProgress = ({ const maxLabel = isNil(max) ? i18n('value_no-limit') : max; + let tooltipContent = currentTooltip; + if (isBelowMin) { + tooltipContent = belowLimitTooltip; + } else if (isAboveMax) { + tooltipContent = aboveLimitTooltip; + } + return ( - - {isBelowMin && ( + + + {isBelowMin && ( + + + +
+ + {partitionsCount} + +
+
+ )} + - + -
+
- {partitionsCount} + {min} -
- - )} - - - - -
- - {min} - - - {maxLabel} - -
-
- - {isAboveMax && ( - - - -
- {partitionsCount} + {maxLabel}
- )} - + + {isAboveMax && ( + + + +
+ + {partitionsCount} + +
+
+ )} + + ); }; diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts index 28439ad8cc..773eae7758 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts @@ -1,5 +1,6 @@ import {isNil} from 'lodash'; +import {FULL_FILL_VALUE} from './PartitionsProgress'; import i18n from './i18n'; export interface PartitionsProgressCalcResult { @@ -40,7 +41,7 @@ export function calcPartitionsProgress( const mainSegmentUnits = isBelowMin ? 4 : 1; const rightSegmentUnits = 0; - const mainProgressValue = partitionsCount < min ? 0 : 100; + const mainProgressValue = partitionsCount < min ? 0 : FULL_FILL_VALUE; return { min, @@ -77,7 +78,7 @@ export function calcPartitionsProgress( if (partitionsCount <= min) { mainProgressValue = 0; } else if (partitionsCount >= max) { - mainProgressValue = 100; + mainProgressValue = FULL_FILL_VALUE; } else { mainProgressValue = ((partitionsCount - min) / range) * 100; } diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx index 1f53155790..8956945c8d 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx @@ -46,7 +46,7 @@ export const TableInfo = ({data, type}: TableInfoProps) => {
{i18n('title')}
} + renderEmptyState={() => null} />
{tableStatsInfo ? ( From dd87209887fd83cfff6d909b111330c32d905a04 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Wed, 10 Dec 2025 20:06:12 +0300 Subject: [PATCH 08/11] Fix bugs --- .../PartitionsProgress.scss | 22 ++-------------- .../PartitionsProgress/PartitionsProgress.tsx | 25 +++++++++---------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss index 740f0e49a7..8d7c09407c 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss @@ -3,8 +3,7 @@ display: flex; flex-basis: 0; - &_left, - &_right { + &_additional { min-width: 20px; } @@ -14,8 +13,7 @@ } &__segment-bar { - &_left, - &_right { + &_additional { --g-progress-filled-background-color: var(--g-color-base-danger-heavy); } @@ -25,22 +23,6 @@ } } - &__segment-labels { - display: flex; - - &_left { - justify-content: flex-start; - } - - &_right { - justify-content: flex-end; - } - - &_main { - justify-content: space-between; - } - } - &__segment-touched { padding: var(--g-spacing-2); diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx index eb68bdd14d..366bf3705f 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -17,12 +17,11 @@ interface PartitionsProgressProps { className?: string; } -type SegmentPosition = 'left' | 'main' | 'right'; +type SegmentPosition = 'main' | 'additional'; const SEGMENT_MODS: Record> = { - left: {left: true}, + additional: {additional: true}, main: {main: true}, - right: {right: true}, }; export const FULL_FILL_VALUE = 100; @@ -93,15 +92,15 @@ export const PartitionsProgress = ({ style={{flexGrow: leftSegmentUnits}} direction="column" gap="2" - className={b('segment', SEGMENT_MODS.left)} + className={b('segment', SEGMENT_MODS.additional)} > - + -
+ {partitionsCount} -
+ )} @@ -113,30 +112,30 @@ export const PartitionsProgress = ({ > -
+ {min} {maxLabel} -
+ {isAboveMax && ( - + -
+ {partitionsCount} -
+
)} From 57bb8c0b90869eca4ff692fe757ede8150ea2309 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Thu, 11 Dec 2025 17:36:37 +0300 Subject: [PATCH 09/11] Fix window --- .../Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx | 4 +--- src/types/window.d.ts | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx index 8956945c8d..994d703cd6 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx @@ -27,9 +27,7 @@ export const TableInfo = ({data, type}: TableInfoProps) => { } = React.useMemo(() => prepareTableInfo(data, type), [data, type]); // Feature flag: show partitions progress only if WINDOW_SHOW_TABLE_SETTINGS is truthy - const isPartitionsProgressEnabled = Boolean( - (window as unknown as {WINDOW_SHOW_TABLE_SETTINGS?: unknown}).WINDOW_SHOW_TABLE_SETTINGS, - ); + const isPartitionsProgressEnabled = Boolean(window.WINDOW_SHOW_TABLE_SETTINGS); return (
diff --git a/src/types/window.d.ts b/src/types/window.d.ts index cb10abf0a8..abd9bfa486 100644 --- a/src/types/window.d.ts +++ b/src/types/window.d.ts @@ -45,5 +45,7 @@ interface Window { api: import('../services/api/index').YdbEmbeddedAPI; + WINDOW_SHOW_TABLE_SETTINGS?: boolean; + [key: `yaCounter${number}`]: any; } From 3de084bbeb02fa1de874570e963762ee82c5157d Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Mon, 15 Dec 2025 17:25:39 +0300 Subject: [PATCH 10/11] Fix tests --- .../PartitionsProgress/PartitionsProgress.tsx | 35 +-- .../__test__/calcPartitionsProgress.test.ts | 199 ++++++++++++++++++ .../TableInfo/PartitionsProgress/helpers.ts | 124 +++-------- .../TableInfo/PartitionsProgress/utils.ts | 116 ++++++++++ .../Overview/TableInfo/TableInfo.tsx | 8 +- .../Overview/TableInfo/i18n/en.json | 34 +-- .../Overview/TableInfo/prepareTableInfo.tsx | 30 +-- 7 files changed, 384 insertions(+), 162 deletions(-) create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/__test__/calcPartitionsProgress.test.ts create mode 100644 src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/utils.ts diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx index 366bf3705f..d326adaa36 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -3,8 +3,9 @@ import {isNil} from 'lodash'; import {cn} from '../../../../../../utils/cn'; -import {calcPartitionsProgress, getPartitionsLabel} from './helpers'; +import {getPartitionsTooltip} from './helpers'; import i18n from './i18n'; +import {FULL_FILL_VALUE, calcPartitionsProgress} from './utils'; import './PartitionsProgress.scss'; @@ -24,8 +25,6 @@ const SEGMENT_MODS: Record> = { main: {main: true}, }; -export const FULL_FILL_VALUE = 100; - interface SegmentProgressBarProps { position: SegmentPosition; value: number; @@ -56,36 +55,18 @@ export const PartitionsProgress = ({ mainProgressValue, } = calcPartitionsProgress(minPartitions, maxPartitions, partitionsCount); - const partitionsLabel = getPartitionsLabel(partitionsCount); - - const belowLimitTooltip = i18n('tooltip_partitions-below-limit', { - count: partitionsCount, - diff: partitionsBelowMin, - partitions: partitionsLabel, - }); - - const aboveLimitTooltip = i18n('tooltip_partitions-above-limit', { + const tooltip = getPartitionsTooltip({ count: partitionsCount, - diff: partitionsAboveMax, - partitions: partitionsLabel, - }); - - const currentTooltip = i18n('tooltip_partitions-current', { - count: partitionsCount, - partitions: partitionsLabel, + belowMin: partitionsBelowMin, + aboveMax: partitionsAboveMax, + isBelowMin: isBelowMin, + isAboveMax: isAboveMax, }); const maxLabel = isNil(max) ? i18n('value_no-limit') : max; - let tooltipContent = currentTooltip; - if (isBelowMin) { - tooltipContent = belowLimitTooltip; - } else if (isAboveMax) { - tooltipContent = aboveLimitTooltip; - } - return ( - + {isBelowMin && ( { + describe('when maxPartitions is not provided', () => { + test('should reserve fixed 20% (1:4) for below-min segment when count < min', () => { + // minPartitions = 5, partitionsCount = 2 + const res = calcPartitionsProgress(5, undefined, 2); + + expect(res).toEqual({ + min: 5, + max: undefined, + + partitionsBelowMin: 3, + partitionsAboveMax: 0, + + isBelowMin: true, + isAboveMax: false, + + leftSegmentUnits: 1, + mainSegmentUnits: 4, + rightSegmentUnits: 0, + + mainProgressValue: 0, + }); + }); + + test('should not show warning segment when count >= min', () => { + // minPartitions = 3, partitionsCount = 3 + const res = calcPartitionsProgress(3, undefined, 3); + + expect(res).toEqual({ + min: 3, + max: undefined, + + partitionsBelowMin: 0, + partitionsAboveMax: 0, + + isBelowMin: false, + isAboveMax: false, + + leftSegmentUnits: 0, + mainSegmentUnits: 1, + rightSegmentUnits: 0, + + mainProgressValue: FULL_FILL_VALUE, + }); + }); + }); + + describe('when maxPartitions is provided', () => { + test('should calculate proportional progress inside [min, max]', () => { + // minPartitions = 2, maxPartitions = 6, partitionsCount = 4 => (4-2)/(6-2)=0.5 => 50% + const res = calcPartitionsProgress(2, 6, 4); + + expect(res).toEqual({ + min: 2, + max: 6, + + partitionsBelowMin: 0, + partitionsAboveMax: 0, + + isBelowMin: false, + isAboveMax: false, + + leftSegmentUnits: 0, + mainSegmentUnits: 4, + rightSegmentUnits: 0, + + mainProgressValue: 50, + }); + }); + + test('should show left overflow and empty main when count < min', () => { + // minPartitions = 5, maxPartitions = 10, partitionsCount = 2 + const res = calcPartitionsProgress(5, 10, 2); + + expect(res).toEqual({ + min: 5, + max: 10, + + partitionsBelowMin: 3, + partitionsAboveMax: 0, + + isBelowMin: true, + isAboveMax: false, + + leftSegmentUnits: 3, + mainSegmentUnits: 5, + rightSegmentUnits: 0, + + mainProgressValue: 0, + }); + }); + + test('should show right overflow and full main when count > max', () => { + // minPartitions = 3, maxPartitions = 10, partitionsCount = 13 + const res = calcPartitionsProgress(3, 10, 13); + + expect(res).toEqual({ + min: 3, + max: 10, + + partitionsBelowMin: 0, + partitionsAboveMax: 3, + + isBelowMin: false, + isAboveMax: true, + + leftSegmentUnits: 0, + mainSegmentUnits: 7, + rightSegmentUnits: 3, + + mainProgressValue: FULL_FILL_VALUE, + }); + }); + + test('should fill main segment when min === max and count equals limits', () => { + // minPartitions = 5, maxPartitions = 5, partitionsCount = 5 + const res = calcPartitionsProgress(5, 5, 5); + + expect(res).toEqual({ + min: 5, + max: 5, + + partitionsBelowMin: 0, + partitionsAboveMax: 0, + + isBelowMin: false, + isAboveMax: false, + + leftSegmentUnits: 0, + mainSegmentUnits: 1, + rightSegmentUnits: 0, + + mainProgressValue: FULL_FILL_VALUE, + }); + }); + + test('should keep main segment empty when min === max and count < min', () => { + // minPartitions = 5, maxPartitions = 5, partitionsCount = 3 + const res = calcPartitionsProgress(5, 5, 3); + + expect(res).toEqual({ + min: 5, + max: 5, + + partitionsBelowMin: 2, + partitionsAboveMax: 0, + + isBelowMin: true, + isAboveMax: false, + + leftSegmentUnits: 2, + mainSegmentUnits: 1, + rightSegmentUnits: 0, + + mainProgressValue: 0, + }); + }); + + test('should show right overflow and fill main when min === max and count > max', () => { + // minPartitions = 5, maxPartitions = 5, partitionsCount = 7 + const res = calcPartitionsProgress(5, 5, 7); + + expect(res).toEqual({ + min: 5, + max: 5, + + partitionsBelowMin: 0, + partitionsAboveMax: 2, + + isBelowMin: false, + isAboveMax: true, + + leftSegmentUnits: 0, + mainSegmentUnits: 1, + rightSegmentUnits: 2, + + mainProgressValue: FULL_FILL_VALUE, + }); + }); + + test('should clamp maxPartitions to minPartitions when max < min', () => { + // minPartitions = 5, maxPartitions = 2, partitionsCount = 6 + const res = calcPartitionsProgress(5, 2, 6); + + expect(res.min).toBe(5); + expect(res.max).toBe(5); + }); + }); + + describe('min clamping', () => { + test('should clamp minPartitions to at least 1', () => { + // minPartitions = 0, partitionsCount = 1 + const res = calcPartitionsProgress(0, undefined, 1); + expect(res.min).toBe(1); + }); + }); +}); diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts index 773eae7758..f752dcf0ef 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/helpers.ts @@ -1,109 +1,35 @@ -import {isNil} from 'lodash'; - -import {FULL_FILL_VALUE} from './PartitionsProgress'; import i18n from './i18n'; -export interface PartitionsProgressCalcResult { - min: number; - max?: number; - - partitionsBelowMin: number; - partitionsAboveMax: number; +export const getPartitionsNoun = (count: number) => + count === 1 ? i18n('value_partition-one') : i18n('value_partition-many'); +export function getPartitionsTooltip(params: { + count: number; + belowMin: number; + aboveMax: number; isBelowMin: boolean; isAboveMax: boolean; - - leftSegmentUnits: number; - mainSegmentUnits: number; - rightSegmentUnits: number; - - mainProgressValue: number; -} - -export function calcPartitionsProgress( - minPartitions: number, - maxPartitions: number | undefined, - partitionsCount: number, -): PartitionsProgressCalcResult { - const min = minPartitions; - - const hasMaxLimit = !isNil(maxPartitions); - - if (!hasMaxLimit) { - const partitionsBelowMin = Math.max(0, min - partitionsCount); - const partitionsAboveMax = 0; - const isBelowMin = partitionsBelowMin > 0; - const isAboveMax = false; - - // When max limit is not provided, reserve a fixed 20% of the total width - // for the "below min" segment (1:4 ratio between warning and main segments). - const leftSegmentUnits = isBelowMin ? 1 : 0; - const mainSegmentUnits = isBelowMin ? 4 : 1; - const rightSegmentUnits = 0; - - const mainProgressValue = partitionsCount < min ? 0 : FULL_FILL_VALUE; - - return { - min, - max: undefined, - - partitionsBelowMin, - partitionsAboveMax, - - isBelowMin, - isAboveMax, - - leftSegmentUnits, - mainSegmentUnits, - rightSegmentUnits, - - mainProgressValue, - }; +}) { + const partitions = getPartitionsNoun(params.count); + + if (params.isBelowMin) { + return i18n('tooltip_partitions-below-limit', { + count: params.count, + diff: params.belowMin, + partitions, + }); } - const max = Math.max(maxPartitions as number, minPartitions); - - const range = Math.max(0, max - min); - - const partitionsBelowMin = Math.max(0, min - partitionsCount); - const partitionsAboveMax = Math.max(0, partitionsCount - max); - - const isBelowMin = partitionsBelowMin > 0; - const isAboveMax = partitionsAboveMax > 0; - - const mainSegmentUnits = range || 1; - - let mainProgressValue = 0; - if (range > 0) { - if (partitionsCount <= min) { - mainProgressValue = 0; - } else if (partitionsCount >= max) { - mainProgressValue = FULL_FILL_VALUE; - } else { - mainProgressValue = ((partitionsCount - min) / range) * 100; - } + if (params.isAboveMax) { + return i18n('tooltip_partitions-above-limit', { + count: params.count, + diff: params.aboveMax, + partitions, + }); } - const leftSegmentUnits = isBelowMin ? partitionsBelowMin : 0; - const rightSegmentUnits = isAboveMax ? partitionsAboveMax : 0; - - return { - min, - max, - - partitionsBelowMin, - partitionsAboveMax, - - isBelowMin, - isAboveMax, - - leftSegmentUnits, - mainSegmentUnits, - rightSegmentUnits, - - mainProgressValue, - }; + return i18n('tooltip_partitions-current', { + count: params.count, + partitions, + }); } - -export const getPartitionsLabel = (count: number) => - count === 1 ? i18n('value_partition-one') : i18n('value_partition-many'); diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/utils.ts b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/utils.ts new file mode 100644 index 0000000000..8c108c9fb8 --- /dev/null +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/utils.ts @@ -0,0 +1,116 @@ +import {isNil} from 'lodash'; + +export const FULL_FILL_VALUE = 100; + +// 20% warning segment when max is not provided: 1 / (1 + 4) = 20% +const NO_MAX_LEFT_UNITS = 1; +const NO_MAX_MAIN_UNITS = 4; + +export interface PartitionsProgressCalcResult { + min: number; + max?: number; + + partitionsBelowMin: number; + partitionsAboveMax: number; + + isBelowMin: boolean; + isAboveMax: boolean; + + leftSegmentUnits: number; + mainSegmentUnits: number; + rightSegmentUnits: number; + + mainProgressValue: number; +} + +export function calcPartitionsProgress( + minPartitions: number, + maxPartitions: number | undefined, + partitionsCount: number, +): PartitionsProgressCalcResult { + const min = Math.max(1, minPartitions); + + if (isNil(maxPartitions)) { + return calcPartitionsProgressWithoutMax(min, partitionsCount); + } + + return calcPartitionsProgressWithMax(min, maxPartitions, partitionsCount); +} + +export function calcPartitionsProgressWithoutMax( + min: number, + count: number, +): PartitionsProgressCalcResult { + const partitionsBelowMin = Math.max(0, min - count); + const isBelowMin = partitionsBelowMin > 0; + + const leftSegmentUnits = isBelowMin ? NO_MAX_LEFT_UNITS : 0; + const mainSegmentUnits = isBelowMin ? NO_MAX_MAIN_UNITS : 1; + + return { + min, + max: undefined, + + partitionsBelowMin, + partitionsAboveMax: 0, + + isBelowMin, + isAboveMax: false, + + leftSegmentUnits, + mainSegmentUnits, + rightSegmentUnits: 0, + + mainProgressValue: count < min ? 0 : FULL_FILL_VALUE, + }; +} + +export function calcPartitionsProgressWithMax( + min: number, + max: number, + count: number, +): PartitionsProgressCalcResult { + const normalizedMax = Math.max(max, min); + const range = Math.max(0, normalizedMax - min); + + const partitionsBelowMin = Math.max(0, min - count); + const partitionsAboveMax = Math.max(0, count - normalizedMax); + + const isBelowMin = partitionsBelowMin > 0; + const isAboveMax = partitionsAboveMax > 0; + + const mainProgressValue = calcMainProgressValue(min, normalizedMax, range, count); + + return { + min, + max: normalizedMax, + + partitionsBelowMin, + partitionsAboveMax, + + isBelowMin, + isAboveMax, + + leftSegmentUnits: isBelowMin ? partitionsBelowMin : 0, + mainSegmentUnits: range || 1, + rightSegmentUnits: isAboveMax ? partitionsAboveMax : 0, + + mainProgressValue, + }; +} + +function calcMainProgressValue(min: number, max: number, range: number, count: number) { + if (range === 0) { + return count >= min ? FULL_FILL_VALUE : 0; + } + + if (count <= min) { + return 0; + } + + if (count >= max) { + return FULL_FILL_VALUE; + } + + return ((count - min) / range) * 100; +} diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx index 994d703cd6..064e92b1d4 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx @@ -31,7 +31,7 @@ export const TableInfo = ({data, type}: TableInfoProps) => { return (
-
{i18n('title')}
+
{i18n('title_partitioning')}
{isPartitionsProgressEnabled && partitionProgressConfig && (
{ null} /> @@ -64,13 +64,13 @@ export const TableInfo = ({data, type}: TableInfoProps) => {
null} /> null} /> diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json b/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json index 8de7d5119f..5ad08ad3e3 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json @@ -1,21 +1,21 @@ { - "title": "Partitioning", - "tableStats": "Stats", - "tabletMetrics": "Metrics", - "partitionConfig": "Partition Config", + "title_partitioning": "Partitioning", + "title_table-stats": "Stats", + "title_tablet-metrics": "Metrics", + "title_partition-config": "Partition config", - "label.ttl": "TTL for rows", - "value.ttl": "column: '{{columnName}}', expire after: {{expireTime}}", - "label.standalone": "Standalone", - "label.partitioning": "Partitioning", - "label.partitioning-by-size": "Partitioning by size", - "value.partitioning-by-size.enabled": "Enabled, split size: {{size}}", - "label.partitioning-by-load": "Partitioning by load", - "label.partitions-min": "Min number of partitions", - "label.partitions-max": "Max number of partitions", - "label.read-replicas": "Read replicas (followers)", - "label.bloom-filter": "Bloom filter", + "field_ttl-for-rows": "TTL for rows", + "field_standalone": "Standalone", + "field_partitioning": "Partitioning", + "field_partitioning-by-size": "Partitioning by size", + "field_partitioning-by-load": "Partitioning by load", + "field_min-partitions-count": "Min number of partitions", + "field_max-partitions-count": "Max number of partitions", + "field_read-replicas": "Read replicas (followers)", + "field_bloom-filter": "Bloom filter", - "enabled": "Enabled", - "disabled": "Disabled" + "value_ttl-config": "column: '{{columnName}}', expire after: {{expireTime}}", + "value_partitioning-by-size-enabled": "Enabled, split size: {{size}}", + "value_enabled": "Enabled", + "value_disabled": "Disabled" } diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx index 7740f17b42..97eea34220 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.tsx @@ -34,12 +34,12 @@ const isInStoreColumnTable = (table: TColumnTableDescription) => { const prepareTTL = (ttl: TTTLSettings | TColumnDataLifeCycle) => { // ExpireAfterSeconds could be 0 if (ttl.Enabled && ttl.Enabled.ColumnName && ttl.Enabled.ExpireAfterSeconds !== undefined) { - const value = i18n('value.ttl', { + const value = i18n('value_ttl-config', { columnName: ttl.Enabled.ColumnName, expireTime: formatDurationToShortTimeFormat(ttl.Enabled.ExpireAfterSeconds * 1000, 1), }); - return {label: i18n('label.ttl'), value}; + return {label: i18n('field_ttl-for-rows'), value}; } return undefined; }; @@ -48,7 +48,7 @@ function prepareColumnTableGeneralInfo(columnTable: TColumnTableDescription) { const columnTableGeneralInfo: InfoViewerItem[] = []; columnTableGeneralInfo.push({ - label: i18n('label.standalone'), + label: i18n('field_standalone'), value: String(!isInStoreColumnTable(columnTable)), }); @@ -57,7 +57,7 @@ function prepareColumnTableGeneralInfo(columnTable: TColumnTableDescription) { const content = `PARTITION BY HASH(${columns})`; columnTableGeneralInfo.push({ - label: i18n('label.partitioning'), + label: i18n('field_partitioning'), value: ( {content} @@ -83,27 +83,27 @@ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings? const partitioningBySize = PartitioningPolicy.SizeToSplit && Number(PartitioningPolicy.SizeToSplit) > 0 - ? i18n('value.partitioning-by-size.enabled', { + ? i18n('value_partitioning-by-size-enabled', { size: formatBytes(PartitioningPolicy.SizeToSplit), }) - : i18n('disabled'); + : i18n('value_disabled'); const partitioningByLoad = PartitioningPolicy.SplitByLoadSettings?.Enabled - ? i18n('enabled') - : i18n('disabled'); + ? i18n('value_enabled') + : i18n('value_disabled'); generalTableInfo.push( - {label: i18n('label.partitioning-by-size'), value: partitioningBySize}, - {label: i18n('label.partitioning-by-load'), value: partitioningByLoad}, + {label: i18n('field_partitioning-by-size'), value: partitioningBySize}, + {label: i18n('field_partitioning-by-load'), value: partitioningByLoad}, { - label: i18n('label.partitions-min'), + label: i18n('field_min-partitions-count'), value: formatNumber(PartitioningPolicy.MinPartitionsCount || 0), }, ); if (PartitioningPolicy.MaxPartitionsCount) { generalTableInfo.push({ - label: i18n('label.partitions-max'), + label: i18n('field_max-partitions-count'), value: formatNumber(PartitioningPolicy.MaxPartitionsCount), }); } @@ -120,7 +120,7 @@ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings? readReplicasConfig = `ANY_AZ: ${FollowerCount}`; } - generalTableInfo.push({label: i18n('label.read-replicas'), value: readReplicasConfig}); + generalTableInfo.push({label: i18n('field_read-replicas'), value: readReplicasConfig}); } if (TTLSettings) { @@ -132,8 +132,8 @@ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings? if (!isNil(EnableFilterByKey)) { generalTableInfo.push({ - label: i18n('label.bloom-filter'), - value: EnableFilterByKey ? i18n('enabled') : i18n('disabled'), + label: i18n('field_bloom-filter'), + value: EnableFilterByKey ? i18n('value_enabled') : i18n('value_disabled'), }); } From 9f9c6b1515cd092bd885c028acf92095cdf198a8 Mon Sep 17 00:00:00 2001 From: Daria Vorontsova Date: Mon, 15 Dec 2025 19:26:06 +0300 Subject: [PATCH 11/11] Fix bugs --- .../PartitionsProgress.scss | 31 ++++++++++++++++-- .../PartitionsProgress/PartitionsProgress.tsx | 32 +++++++++++++++---- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss index 8d7c09407c..2fbe6073f9 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.scss @@ -13,13 +13,38 @@ } &__segment-bar { + --segment-filled-bg-color: var(--g-color-base-neutral-heavy); + --segment-empty-bg-color: var(--g-color-base-neutral-light); + overflow: hidden; + + height: 10px; + + border-radius: var(--g-border-radius-xs); + background-color: var(--segment-empty-bg-color); + &_additional { - --g-progress-filled-background-color: var(--g-color-base-danger-heavy); + --segment-filled-bg-color: var(--g-color-base-danger-heavy); + --segment-empty-bg-color: var(--g-color-base-danger-light); } &_main { - --g-progress-filled-background-color: var(--g-color-base-info-heavy); - --g-progress-empty-background-color: var(--g-color-base-info-light); + --segment-filled-bg-color: var(--g-color-base-info-heavy); + --segment-empty-bg-color: var(--g-color-base-info-light); + } + } + + &__segment-fill { + height: 100%; + + background-color: var(--segment-filled-bg-color); + + transition: + transform 0.6s ease, + width 0.6s ease, + background-color 0.6s ease; + + &_min-fill { + min-width: 20px; } } diff --git a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx index d326adaa36..04edd1a941 100644 --- a/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx +++ b/src/containers/Tenant/Diagnostics/Overview/TableInfo/PartitionsProgress/PartitionsProgress.tsx @@ -1,4 +1,4 @@ -import {Flex, Popover, Progress, Text} from '@gravity-ui/uikit'; +import {Flex, Popover, Text} from '@gravity-ui/uikit'; import {isNil} from 'lodash'; import {cn} from '../../../../../../utils/cn'; @@ -28,13 +28,24 @@ const SEGMENT_MODS: Record> = { interface SegmentProgressBarProps { position: SegmentPosition; value: number; + withMinFill?: boolean; } -const SegmentProgressBar = ({position, value}: SegmentProgressBarProps) => ( -
- -
-); +const SegmentProgressBar = ({position, value, withMinFill}: SegmentProgressBarProps) => { + const width = `${value}%`; + + return ( +
+
+
+ ); +}; export const PartitionsProgress = ({ minPartitions, @@ -65,6 +76,9 @@ export const PartitionsProgress = ({ const maxLabel = isNil(max) ? i18n('value_no-limit') : max; + const hasAdditionalSegments = isBelowMin || isAboveMax; + const withMinFill = !hasAdditionalSegments; + return ( @@ -91,7 +105,11 @@ export const PartitionsProgress = ({ style={{flexGrow: mainSegmentUnits}} gap="2" > - +