Skip to content

Commit ac0dcb8

Browse files
authored
fix(storage): finish BS capacity metrics MVP for Storage/Nodes (#4107)
1 parent a29c584 commit ac0dcb8

18 files changed

Lines changed: 179 additions & 51 deletions

File tree

src/components/PaginatedTable/PaginatedTable.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
RenderEmptyDataMessage,
1717
RenderErrorMessage,
1818
} from './types';
19+
import {isSortColumnAvailable} from './utils';
1920

2021
import './PaginatedTable.scss';
2122

@@ -65,6 +66,7 @@ export const PaginatedTable = <T, F>({
6566
usePaginatedTableState();
6667

6768
const {sortParams, foundEntities} = tableState;
69+
const activeSortParams = isSortColumnAvailable(sortParams, columns) ? sortParams : undefined;
6870

6971
const tableRef = React.useRef<HTMLDivElement>(null);
7072

@@ -122,7 +124,7 @@ export const PaginatedTable = <T, F>({
122124
fetchData={fetchData}
123125
filters={filters}
124126
tableName={tableName}
125-
sortParams={sortParams}
127+
sortParams={activeSortParams}
126128
getRowClassName={getRowClassName}
127129
onRowClick={onRowClick}
128130
renderErrorMessage={renderErrorMessage}

src/components/PaginatedTable/TableHead.tsx

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ interface TableHeadCellProps<T> {
6666
defaultSortOrder: SortOrderType;
6767
onSort?: (columnName: string) => void;
6868
rowHeight: number;
69-
onCellMount?: (element: Element) => void;
70-
onCellUnMount?: (element: Element) => void;
7169
onColumnsResize?: HandleTableColumnsResize;
7270
}
7371

@@ -78,24 +76,10 @@ export const TableHeadCell = <T,>({
7876
defaultSortOrder,
7977
onSort,
8078
rowHeight,
81-
onCellMount,
82-
onCellUnMount,
8379
onColumnsResize,
8480
}: TableHeadCellProps<T>) => {
8581
const cellWrapperRef = React.useRef<HTMLTableCellElement>(null);
8682

87-
React.useEffect(() => {
88-
const cellWrapper = cellWrapperRef.current;
89-
if (cellWrapper) {
90-
onCellMount?.(cellWrapper);
91-
}
92-
return () => {
93-
if (cellWrapper) {
94-
onCellUnMount?.(cellWrapper);
95-
}
96-
};
97-
}, [onCellMount, onCellUnMount]);
98-
9983
const getCurrentColumnWidth = React.useCallback(() => {
10084
return cellWrapperRef.current?.getBoundingClientRect().width;
10185
}, []);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {isSortColumnAvailable} from '../utils';
2+
3+
describe('isSortColumnAvailable', () => {
4+
test('returns false when the active sort column is not available', () => {
5+
expect(
6+
isSortColumnAvailable({columnId: 'DiskSpaceUsage'}, [{name: 'NodeId'}, {name: 'Host'}]),
7+
).toBe(false);
8+
});
9+
10+
test('returns true when the active sort column is available or sorting is inactive', () => {
11+
const columns = [{name: 'NodeId'}, {name: 'DiskSpaceUsage'}];
12+
13+
expect(isSortColumnAvailable({columnId: 'DiskSpaceUsage'}, columns)).toBe(true);
14+
expect(isSortColumnAvailable({}, columns)).toBe(true);
15+
expect(isSortColumnAvailable(undefined, columns)).toBe(true);
16+
});
17+
});

src/components/PaginatedTable/utils.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import React from 'react';
22

3+
import type {SortParams} from './types';
4+
5+
export function isSortColumnAvailable(
6+
sortParams: SortParams | undefined,
7+
columns: Array<{name: string}>,
8+
) {
9+
return !sortParams?.columnId || columns.some((column) => column.name === sortParams.columnId);
10+
}
11+
312
// invoke passed function at most once per animation frame
413
// eslint-disable-next-line @typescript-eslint/no-explicit-any
514
export function rafThrottle<Fn extends (...args: any[]) => any>(fn: Fn) {

src/components/nodesColumns/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const NODES_COLUMNS_IDS = {
3939
PileName: 'PileName',
4040
PDiskUsage: CAPACITY_METRICS_COLUMN_IDS.MaxPDiskUsage,
4141
VDiskSlotUsage: CAPACITY_METRICS_COLUMN_IDS.MaxVDiskSlotUsage,
42+
VDiskRawUsage: CAPACITY_METRICS_COLUMN_IDS.MaxVDiskRawUsage,
4243
CapacityAlert: CAPACITY_METRICS_COLUMN_IDS.CapacityAlert,
4344
} as const;
4445

@@ -147,6 +148,9 @@ export const NODES_COLUMNS_TITLES = {
147148
get MaxVDiskSlotUsage() {
148149
return CAPACITY_METRICS_COLUMN_TITLES.MaxVDiskSlotUsage;
149150
},
151+
get MaxVDiskRawUsage() {
152+
return CAPACITY_METRICS_COLUMN_TITLES.MaxVDiskRawUsage;
153+
},
150154
get CapacityAlert() {
151155
return CAPACITY_METRICS_COLUMN_TITLES.CapacityAlert;
152156
},
@@ -242,6 +246,7 @@ export const NODES_COLUMNS_TO_DATA_FIELDS: Record<NodesColumnId, NodesRequiredFi
242246
PileName: ['PileName'],
243247
MaxPDiskUsage: ['MaxPDiskUsage'],
244248
MaxVDiskSlotUsage: ['MaxVDiskSlotUsage'],
249+
MaxVDiskRawUsage: ['MaxVDiskRawUsage'],
245250
CapacityAlert: ['CapacityAlert'],
246251
};
247252

@@ -275,6 +280,7 @@ const NODES_COLUMNS_TO_SORT_FIELDS: Record<NodesColumnId, NodesSortValue | undef
275280
PileName: undefined,
276281
MaxPDiskUsage: 'MaxPDiskUsage',
277282
MaxVDiskSlotUsage: 'MaxVDiskSlotUsage',
283+
MaxVDiskRawUsage: 'MaxVDiskRawUsage',
278284
CapacityAlert: 'CapacityAlert',
279285
};
280286

src/containers/Storage/PaginatedStorageNodes/StorageNodesControls.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {usePaginatedTableState} from '../../../components/PaginatedTable/Paginat
77
import {Search} from '../../../components/Search/Search';
88
import {UptimeFilter} from '../../../components/UptimeFIlter';
99
import {useBlobStorageCapacityMetricsEnabled} from '../../../store/reducers/capabilities/hooks';
10-
import {STORAGE_NODES_GROUP_BY_OPTIONS} from '../PaginatedStorageNodesTable/columns/constants';
10+
import {getStorageNodesGroupByOptions} from '../PaginatedStorageNodesTable/columns/constants';
1111
import {StorageTypeFilter} from '../StorageTypeFilter/StorageTypeFilter';
1212
import {StorageVisibleEntitiesFilter} from '../StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter';
1313
import i18n from '../i18n';
@@ -46,15 +46,10 @@ export function StorageNodesControls({
4646

4747
const blobMetricsEnabled = useBlobStorageCapacityMetricsEnabled();
4848

49-
const nodesGroupByOptions = React.useMemo(() => {
50-
const skippedValues: string[] = [];
51-
52-
if (!blobMetricsEnabled) {
53-
skippedValues.push('CapacityAlert');
54-
}
55-
56-
return STORAGE_NODES_GROUP_BY_OPTIONS.filter((opt) => !skippedValues.includes(opt.value));
57-
}, [blobMetricsEnabled]);
49+
const nodesGroupByOptions = React.useMemo(
50+
() => getStorageNodesGroupByOptions(blobMetricsEnabled),
51+
[blobMetricsEnabled],
52+
);
5853

5954
const handleGroupBySelectUpdate = (value: string[]) => {
6055
handleStorageNodesGroupByParamChange(value[0]);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {getStorageNodesGroupByOptions} from '../constants';
2+
3+
describe('getStorageNodesGroupByOptions', () => {
4+
test('keeps legacy disk usage group-by and hides capacity alert when experiment is disabled', () => {
5+
const optionValues = getStorageNodesGroupByOptions(false).map(({value}) => value);
6+
7+
expect(optionValues).toContain('DiskSpaceUsage');
8+
expect(optionValues).not.toContain('CapacityAlert');
9+
});
10+
11+
test('keeps capacity alert group-by and hides legacy disk usage when experiment is enabled', () => {
12+
const optionValues = getStorageNodesGroupByOptions(true).map(({value}) => value);
13+
14+
expect(optionValues).toContain('CapacityAlert');
15+
expect(optionValues).not.toContain('DiskSpaceUsage');
16+
});
17+
});

src/containers/Storage/PaginatedStorageNodesTable/columns/columns.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import DataTable from '@gravity-ui/react-data-table';
33
import {
44
getCapacityAlertColumn,
55
getPDiskUsageColumn,
6+
getVDiskRawUsageColumn,
67
getVDiskSlotUsageColumn,
78
} from '../../../../components/capacityMetricsColumns/columns';
89
import {
@@ -86,6 +87,7 @@ export const getStorageNodesColumns = ({
8687
getTabletsColumn({database}),
8788
getPDiskUsageColumn(),
8889
getVDiskSlotUsageColumn(),
90+
getVDiskRawUsageColumn(),
8991
getCapacityAlertColumn(),
9092
];
9193

src/containers/Storage/PaginatedStorageNodesTable/columns/constants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const STORAGE_NODES_GROUP_BY_PARAMS = [
3232
export const CAPACITY_METRICS_USER_SETTINGS_COLUMNS_IDS: NodesColumnId[] = [
3333
'MaxPDiskUsage',
3434
'MaxVDiskSlotUsage',
35+
'MaxVDiskRawUsage',
3536
'CapacityAlert',
3637
];
3738

@@ -44,6 +45,16 @@ export const STORAGE_NODES_GROUP_BY_OPTIONS: SelectOption[] = STORAGE_NODES_GROU
4445
},
4546
);
4647

48+
export function getStorageNodesGroupByOptions(blobMetricsEnabled: boolean): SelectOption[] {
49+
const skippedValues: NodesGroupByField[] = blobMetricsEnabled
50+
? ['DiskSpaceUsage']
51+
: ['CapacityAlert'];
52+
53+
return STORAGE_NODES_GROUP_BY_OPTIONS.filter(
54+
(option) => !skippedValues.includes(option.value as NodesGroupByField),
55+
);
56+
}
57+
4758
export const storageNodesGroupByParamSchema = z
4859
.custom<
4960
NodesGroupByField | undefined

src/containers/Storage/PaginatedStorageNodesTable/columns/hooks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export function useStorageNodesSelectedColumns({
4141
skipped.push(...CAPACITY_METRICS_USER_SETTINGS_COLUMNS_IDS);
4242
}
4343

44+
if (blobMetricsEnabled) {
45+
skipped.push(NODES_COLUMNS_IDS.DiskSpaceUsage);
46+
}
47+
4448
return skipped;
4549
}, [bridgeModeEnabled, blobMetricsEnabled]);
4650

0 commit comments

Comments
 (0)