ydb-embedded-ui 22.1.0 → 22.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DiskStateProgressBar/AllModeIndicators.js +4 -1
- package/dist/components/DiskStateProgressBar/AllModeIndicators.js.map +1 -1
- package/dist/components/DiskStateProgressBar/DiskIndicator.js +5 -1
- package/dist/components/DiskStateProgressBar/DiskIndicator.js.map +1 -1
- package/dist/components/DiskStateProgressBar/DiskStateProgressBar.scss +50 -8
- package/dist/components/PDiskInfo/PDiskInfo.js +2 -1
- package/dist/components/PDiskInfo/PDiskInfo.js.map +1 -1
- package/dist/components/PDiskPopup/PDiskPopup.js +5 -1
- package/dist/components/PDiskPopup/PDiskPopup.js.map +1 -1
- package/dist/components/PaginatedTable/PaginatedTable.js +27 -15
- package/dist/components/PaginatedTable/PaginatedTable.js.map +1 -1
- package/dist/components/PaginatedTable/PaginatedTableContext.d.ts +2 -3
- package/dist/components/PaginatedTable/PaginatedTableContext.js +10 -11
- package/dist/components/PaginatedTable/PaginatedTableContext.js.map +1 -1
- package/dist/components/PaginatedTable/TableChunk.d.ts +1 -1
- package/dist/components/PaginatedTable/TableChunk.js +2 -1
- package/dist/components/PaginatedTable/TableChunk.js.map +1 -1
- package/dist/components/PaginatedTable/TableChunksRenderer.d.ts +1 -1
- package/dist/components/PaginatedTable/tableCounts.d.ts +19 -0
- package/dist/components/PaginatedTable/tableCounts.js +30 -0
- package/dist/components/PaginatedTable/tableCounts.js.map +1 -0
- package/dist/components/VDisk/VDisk.d.ts +2 -1
- package/dist/components/VDisk/VDisk.js +17 -7
- package/dist/components/VDisk/VDisk.js.map +1 -1
- package/dist/components/VDisk/VDiskWithDonorsStack.d.ts +3 -2
- package/dist/components/VDisk/VDiskWithDonorsStack.js +2 -1
- package/dist/components/VDisk/VDiskWithDonorsStack.js.map +1 -1
- package/dist/components/VDisk/i18n/en.json +3 -1
- package/dist/components/VDisk/i18n/index.d.ts +1 -1
- package/dist/containers/Storage/Disks/Disks.js +1 -3
- package/dist/containers/Storage/Disks/Disks.js.map +1 -1
- package/dist/containers/Storage/PDisk/PDisk.js +9 -2
- package/dist/containers/Storage/PDisk/PDisk.js.map +1 -1
- package/dist/containers/Storage/PDisk/i18n/en.json +1 -0
- package/dist/containers/Storage/PDisk/i18n/index.d.ts +1 -1
- package/dist/containers/Storage/StorageExpertModePanel/StorageGroupsExpertModePanel.js +2 -0
- package/dist/containers/Storage/StorageExpertModePanel/StorageGroupsExpertModePanel.js.map +1 -1
- package/dist/containers/Storage/StorageExpertModePanel/components/DriveTypeLegend.d.ts +1 -0
- package/dist/containers/Storage/StorageExpertModePanel/components/DriveTypeLegend.js +7 -0
- package/dist/containers/Storage/StorageExpertModePanel/components/DriveTypeLegend.js.map +1 -0
- package/dist/containers/Storage/StorageExpertModePanel/components/renderExpertModeLegend.js +5 -0
- package/dist/containers/Storage/StorageExpertModePanel/components/renderExpertModeLegend.js.map +1 -1
- package/dist/containers/Storage/StorageExpertModePanel/constants.d.ts +3 -0
- package/dist/containers/Storage/StorageExpertModePanel/constants.js +1 -0
- package/dist/containers/Storage/StorageExpertModePanel/constants.js.map +1 -1
- package/dist/containers/Storage/StorageExpertModePanel/i18n/en.json +4 -0
- package/dist/containers/Storage/StorageExpertModePanel/i18n/index.d.ts +1 -1
- package/dist/containers/Storage/useStoragePDiskDisplayStateGetter.js +7 -0
- package/dist/containers/Storage/useStoragePDiskDisplayStateGetter.js.map +1 -1
- package/dist/containers/Storage/useStorageQueryParams.d.ts +4 -4
- package/dist/containers/Storage/useStorageVDiskDisplayStateGetter.js +10 -1
- package/dist/containers/Storage/useStorageVDiskDisplayStateGetter.js.map +1 -1
- package/dist/containers/VDiskPage/VDiskPage.js +9 -1
- package/dist/containers/VDiskPage/VDiskPage.js.map +1 -1
- package/dist/store/reducers/table/table.js +6 -0
- package/dist/store/reducers/table/table.js.map +1 -1
- package/dist/store/reducers/topic/topic.js +7 -1
- package/dist/store/reducers/topic/topic.js.map +1 -1
- package/dist/uiFactory/types.d.ts +6 -0
- package/dist/utils/disks/displayState.d.ts +3 -2
- package/dist/utils/disks/displayState.js.map +1 -1
- package/dist/utils/disks/driveType.d.ts +3 -0
- package/dist/utils/disks/driveType.js +27 -0
- package/dist/utils/disks/driveType.js.map +1 -0
- package/dist/utils/disks/getDiskBarTone.d.ts +3 -2
- package/dist/utils/disks/getDiskBarTone.js +4 -1
- package/dist/utils/disks/getDiskBarTone.js.map +1 -1
- package/dist/utils/disks/getPDiskType.d.ts +1 -0
- package/dist/utils/disks/getPDiskType.js +3 -0
- package/dist/utils/disks/getPDiskType.js.map +1 -1
- package/dist/utils/disks/groupBy.d.ts +1 -0
- package/dist/utils/disks/groupBy.js +1 -0
- package/dist/utils/disks/groupBy.js.map +1 -1
- package/dist/utils/disks/iconCalculators.d.ts +1 -1
- package/dist/utils/disks/iconCalculators.js +2 -2
- package/dist/utils/disks/iconCalculators.js.map +1 -1
- package/dist/utils/disks/types.d.ts +1 -1
- package/dist/utils/objectCreationMetrics.d.ts +5 -0
- package/dist/utils/objectCreationMetrics.js +38 -0
- package/dist/utils/objectCreationMetrics.js.map +1 -0
- package/package.json +1 -1
- package/src/components/DiskStateProgressBar/AllModeIndicators.tsx +12 -1
- package/src/components/DiskStateProgressBar/DiskIndicator.tsx +9 -1
- package/src/components/DiskStateProgressBar/DiskStateProgressBar.scss +50 -8
- package/src/components/PDiskInfo/PDiskInfo.tsx +2 -1
- package/src/components/PDiskPopup/PDiskPopup.tsx +5 -1
- package/src/components/PaginatedTable/PaginatedTable.tsx +34 -24
- package/src/components/PaginatedTable/PaginatedTableContext.tsx +14 -19
- package/src/components/PaginatedTable/TableChunk.tsx +3 -2
- package/src/components/PaginatedTable/TableChunksRenderer.tsx +1 -1
- package/src/components/PaginatedTable/tableCounts.ts +50 -0
- package/src/components/VDisk/VDisk.tsx +28 -5
- package/src/components/VDisk/VDiskWithDonorsStack.tsx +5 -1
- package/src/components/VDisk/i18n/en.json +3 -1
- package/src/containers/Storage/Disks/Disks.tsx +2 -4
- package/src/containers/Storage/PDisk/PDisk.tsx +11 -2
- package/src/containers/Storage/PDisk/i18n/en.json +1 -0
- package/src/containers/Storage/StorageExpertModePanel/StorageGroupsExpertModePanel.tsx +2 -0
- package/src/containers/Storage/StorageExpertModePanel/components/DriveTypeLegend.tsx +22 -0
- package/src/containers/Storage/StorageExpertModePanel/components/renderExpertModeLegend.tsx +5 -0
- package/src/containers/Storage/StorageExpertModePanel/constants.ts +1 -0
- package/src/containers/Storage/StorageExpertModePanel/i18n/en.json +4 -0
- package/src/containers/Storage/useStoragePDiskDisplayStateGetter.ts +8 -0
- package/src/containers/Storage/useStorageVDiskDisplayStateGetter.ts +11 -1
- package/src/containers/VDiskPage/VDiskPage.tsx +9 -1
- package/src/store/reducers/table/table.ts +6 -0
- package/src/store/reducers/topic/topic.ts +7 -1
- package/src/uiFactory/types.ts +6 -0
- package/src/utils/disks/displayState.ts +3 -1
- package/src/utils/disks/driveType.ts +30 -0
- package/src/utils/disks/getDiskBarTone.ts +7 -1
- package/src/utils/disks/getPDiskType.ts +4 -0
- package/src/utils/disks/groupBy.ts +1 -0
- package/src/utils/disks/iconCalculators.ts +2 -2
- package/src/utils/disks/types.ts +1 -1
- package/src/utils/objectCreationMetrics.ts +47 -0
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
|
|
61
61
|
border: $border-width solid var(--entity-state-border-color);
|
|
62
62
|
|
|
63
|
-
&#{$block}_striped
|
|
63
|
+
&#{$block}_striped,
|
|
64
|
+
&#{$block}_borderless {
|
|
64
65
|
border: none;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -133,6 +134,36 @@
|
|
|
133
134
|
--entity-state-icon-color: var(--g-color-text-info);
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
&_mode-drivetype {
|
|
138
|
+
@each $type, $theme, $intensity in (ssd misc medium, hdd utility light, nvme info light) {
|
|
139
|
+
&#{$block}_#{$type} {
|
|
140
|
+
--entity-state-background-color: var(--g-color-base-#{$theme}-#{$intensity});
|
|
141
|
+
--ydb-progress-bar-font-color: var(--g-color-text-#{$theme});
|
|
142
|
+
|
|
143
|
+
&#{$block}_highlighted {
|
|
144
|
+
--entity-state-background-color: var(
|
|
145
|
+
--g-color-base-#{$theme}-#{$intensity}-hover
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
#{$block}__text-label {
|
|
151
|
+
overflow: hidden;
|
|
152
|
+
flex-shrink: 1;
|
|
153
|
+
|
|
154
|
+
min-width: 0;
|
|
155
|
+
padding-right: var(--g-spacing-1);
|
|
156
|
+
|
|
157
|
+
white-space: nowrap;
|
|
158
|
+
|
|
159
|
+
mask-image: linear-gradient(
|
|
160
|
+
to right,
|
|
161
|
+
#000 calc(100% - var(--g-spacing-1)),
|
|
162
|
+
transparent
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
136
167
|
&_mode-all {
|
|
137
168
|
&#{$block}_green {
|
|
138
169
|
--entity-state-background-color: transparent;
|
|
@@ -358,18 +389,19 @@
|
|
|
358
389
|
|
|
359
390
|
// Keep N/D colors independent from expert mode-specific backgrounds.
|
|
360
391
|
&_grey {
|
|
361
|
-
--ydb-progress-bar-font-color: var(--g-color-text-
|
|
392
|
+
--ydb-progress-bar-font-color: var(--g-color-text-primary);
|
|
393
|
+
--entity-state-font-color: var(--g-color-text-primary);
|
|
362
394
|
--entity-state-icon-color: var(--g-color-text-secondary);
|
|
363
395
|
--entity-state-border-color: none;
|
|
364
|
-
--entity-state-background-color: var(--g-color-base-neutral-
|
|
365
|
-
--entity-state-fill-color: var(--g-color-base-neutral-
|
|
396
|
+
--entity-state-background-color: var(--g-color-base-neutral-medium);
|
|
397
|
+
--entity-state-fill-color: var(--g-color-base-neutral-medium);
|
|
366
398
|
|
|
367
|
-
color: var(--g-color-text-
|
|
399
|
+
color: var(--g-color-text-primary);
|
|
368
400
|
border: none;
|
|
369
401
|
|
|
370
402
|
&#{$block}_highlighted {
|
|
371
|
-
--entity-state-background-color: var(--g-color-base-neutral-
|
|
372
|
-
--entity-state-fill-color: var(--g-color-base-neutral-
|
|
403
|
+
--entity-state-background-color: var(--g-color-base-neutral-medium-hover);
|
|
404
|
+
--entity-state-fill-color: var(--g-color-base-neutral-medium-hover);
|
|
373
405
|
}
|
|
374
406
|
}
|
|
375
407
|
|
|
@@ -528,7 +560,7 @@
|
|
|
528
560
|
}
|
|
529
561
|
|
|
530
562
|
&__all-mode-missing-data-indicator-icon {
|
|
531
|
-
color:
|
|
563
|
+
color: var(--g-color-text-hint);
|
|
532
564
|
}
|
|
533
565
|
|
|
534
566
|
&__all-mode-front-queues-indicator-slot {
|
|
@@ -576,6 +608,12 @@
|
|
|
576
608
|
|
|
577
609
|
color: var(--ydb-progress-bar-font-color);
|
|
578
610
|
|
|
611
|
+
&_text,
|
|
612
|
+
&_compact {
|
|
613
|
+
color: var(--g-color-text-primary);
|
|
614
|
+
@include mixins.text-caption-2();
|
|
615
|
+
}
|
|
616
|
+
|
|
579
617
|
&_text {
|
|
580
618
|
margin-right: var(--g-spacing-1);
|
|
581
619
|
}
|
|
@@ -621,6 +659,10 @@
|
|
|
621
659
|
|
|
622
660
|
color: var(--entity-state-icon-color, var(--entity-state-border-color));
|
|
623
661
|
|
|
662
|
+
&_missing-data {
|
|
663
|
+
color: var(--g-color-text-hint);
|
|
664
|
+
}
|
|
665
|
+
|
|
624
666
|
&_overlap-top-left {
|
|
625
667
|
position: absolute;
|
|
626
668
|
z-index: 3;
|
|
@@ -5,6 +5,7 @@ import {valueIsDefined} from '../../utils';
|
|
|
5
5
|
import {formatBytes} from '../../utils/bytesParsers';
|
|
6
6
|
import {formatStorageValuesToGb} from '../../utils/dataFormatters/dataFormatters';
|
|
7
7
|
import {createPDiskDeveloperUILink, useHasDeveloperUi} from '../../utils/developerUI/developerUI';
|
|
8
|
+
import {formatPDiskType} from '../../utils/disks/getPDiskType';
|
|
8
9
|
import type {PreparedPDisk} from '../../utils/disks/types';
|
|
9
10
|
import {getPDiskCapacityInfoItems, toInfoViewerItems} from '../DiskCapacityInfo/DiskCapacityInfo';
|
|
10
11
|
import type {InfoViewerItem} from '../InfoViewer';
|
|
@@ -57,7 +58,7 @@ function getPDiskInfo<T extends PreparedPDisk>({
|
|
|
57
58
|
const generalInfo: InfoViewerItem[] = [];
|
|
58
59
|
|
|
59
60
|
if (valueIsDefined(Category)) {
|
|
60
|
-
generalInfo.push({label: pDiskInfoKeyset('type'), value: Type});
|
|
61
|
+
generalInfo.push({label: pDiskInfoKeyset('type'), value: formatPDiskType(Type)});
|
|
61
62
|
}
|
|
62
63
|
if (valueIsDefined(Path)) {
|
|
63
64
|
generalInfo.push({label: pDiskInfoKeyset('path'), value: Path});
|
|
@@ -12,6 +12,7 @@ import {BRAND_BUTTON_CLASS, EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'
|
|
|
12
12
|
import {createPDiskDeveloperUILink, useHasDeveloperUi} from '../../utils/developerUI/developerUI';
|
|
13
13
|
import {getStateSeverity} from '../../utils/disks/calculatePDiskSeverity';
|
|
14
14
|
import {NUMERIC_SEVERITY_TO_LABEL_VIEW} from '../../utils/disks/constants';
|
|
15
|
+
import {formatPDiskType} from '../../utils/disks/getPDiskType';
|
|
15
16
|
import type {PreparedPDisk} from '../../utils/disks/types';
|
|
16
17
|
import {useTypedSelector} from '../../utils/hooks';
|
|
17
18
|
import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery';
|
|
@@ -41,7 +42,10 @@ export const preparePDiskData = (
|
|
|
41
42
|
const {AvailableSize, TotalSize, NodeId, Path, Realtime, Type, Device} = data;
|
|
42
43
|
|
|
43
44
|
const pdiskData: YDBDefinitionListItem[] = [
|
|
44
|
-
{
|
|
45
|
+
{
|
|
46
|
+
name: pDiskPopupKeyset('label_type'),
|
|
47
|
+
content: formatPDiskType(Type) || pDiskPopupKeyset('value_unknown'),
|
|
48
|
+
},
|
|
45
49
|
];
|
|
46
50
|
|
|
47
51
|
if (NodeId) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
import isEqual from 'lodash/isEqual';
|
|
4
|
+
import omit from 'lodash/omit';
|
|
4
5
|
import {useStore} from 'react-redux';
|
|
5
6
|
|
|
6
7
|
import type {RootState} from '../../store';
|
|
@@ -78,14 +79,7 @@ export const PaginatedTable = <T, F>({
|
|
|
78
79
|
}: PaginatedTableProps<T, F>) => {
|
|
79
80
|
const store = useStore<RootState>();
|
|
80
81
|
// Get state and setters from context
|
|
81
|
-
const {
|
|
82
|
-
tableState,
|
|
83
|
-
noBatching,
|
|
84
|
-
setSortParams,
|
|
85
|
-
setTotalEntities,
|
|
86
|
-
setFoundEntities,
|
|
87
|
-
setIsInitialLoad,
|
|
88
|
-
} = usePaginatedTableState();
|
|
82
|
+
const {tableState, noBatching, setSortParams, dispatchCounts} = usePaginatedTableState();
|
|
89
83
|
|
|
90
84
|
const {sortParams, foundEntities} = tableState;
|
|
91
85
|
const activeSortParams = isSortColumnAvailable(sortParams, columns) ? sortParams : undefined;
|
|
@@ -100,6 +94,27 @@ export const PaginatedTable = <T, F>({
|
|
|
100
94
|
setFilters(rawFilters);
|
|
101
95
|
}, [rawFilters]);
|
|
102
96
|
|
|
97
|
+
const nextCountsQuery = omit(
|
|
98
|
+
getTableChunkQueryParams({
|
|
99
|
+
offset: 0,
|
|
100
|
+
limit: chunkSize,
|
|
101
|
+
fetchData,
|
|
102
|
+
filters,
|
|
103
|
+
sortParams: activeSortParams,
|
|
104
|
+
columns,
|
|
105
|
+
tableName,
|
|
106
|
+
noBatching,
|
|
107
|
+
}),
|
|
108
|
+
'offset',
|
|
109
|
+
'fetchData',
|
|
110
|
+
);
|
|
111
|
+
const [countsQuery, setCountsQuery] = React.useState(nextCountsQuery);
|
|
112
|
+
|
|
113
|
+
// Resizing columns must not replay cached chunk responses through a new callback.
|
|
114
|
+
if (!isEqual(countsQuery, nextCountsQuery)) {
|
|
115
|
+
setCountsQuery(nextCountsQuery);
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
const getQueryParams = (offset: number) =>
|
|
104
119
|
getTableChunkQueryParams({
|
|
105
120
|
offset,
|
|
@@ -186,15 +201,16 @@ export const PaginatedTable = <T, F>({
|
|
|
186
201
|
};
|
|
187
202
|
|
|
188
203
|
const handleDataFetched = React.useCallback(
|
|
189
|
-
(data
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
204
|
+
(data: PaginatedTableData<T>) => {
|
|
205
|
+
dispatchCounts({
|
|
206
|
+
type: 'dataReceived',
|
|
207
|
+
query: countsQuery,
|
|
208
|
+
total: data.total,
|
|
209
|
+
found: data.found,
|
|
210
|
+
});
|
|
211
|
+
onDataFetched?.(data);
|
|
196
212
|
},
|
|
197
|
-
[
|
|
213
|
+
[countsQuery, dispatchCounts, onDataFetched],
|
|
198
214
|
);
|
|
199
215
|
|
|
200
216
|
// Set will-change: transform on scroll container if not already set
|
|
@@ -208,15 +224,9 @@ export const PaginatedTable = <T, F>({
|
|
|
208
224
|
}
|
|
209
225
|
}, [scrollContainerRef.current]);
|
|
210
226
|
|
|
211
|
-
// Reset table on initialization and filters change
|
|
212
227
|
React.useLayoutEffect(() => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
setTotalEntities(defaultTotal);
|
|
217
|
-
setFoundEntities(defaultFound);
|
|
218
|
-
setIsInitialLoad(true);
|
|
219
|
-
}, [initialEntitiesCount, setTotalEntities, setFoundEntities, setIsInitialLoad]);
|
|
228
|
+
dispatchCounts({type: 'initialize', query: countsQuery, initialEntitiesCount});
|
|
229
|
+
}, [countsQuery, initialEntitiesCount, dispatchCounts]);
|
|
220
230
|
|
|
221
231
|
const renderTable = () => (
|
|
222
232
|
<table className={b('table')}>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
import type {TableCountsAction} from './tableCounts';
|
|
4
|
+
import {tableCountsReducer} from './tableCounts';
|
|
3
5
|
import type {PaginatedTableState} from './types';
|
|
4
6
|
|
|
5
7
|
// Default state for the table
|
|
@@ -18,18 +20,14 @@ interface PaginatedTableStateContextType {
|
|
|
18
20
|
|
|
19
21
|
// Granular setters
|
|
20
22
|
setSortParams: (params: PaginatedTableState['sortParams']) => void;
|
|
21
|
-
|
|
22
|
-
setFoundEntities: (found: number) => void;
|
|
23
|
-
setIsInitialLoad: (isInitial: boolean) => void;
|
|
23
|
+
dispatchCounts: React.Dispatch<TableCountsAction>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Creating the context with default values
|
|
27
27
|
export const PaginatedTableStateContext = React.createContext<PaginatedTableStateContextType>({
|
|
28
28
|
tableState: defaultTableState,
|
|
29
29
|
setSortParams: () => undefined,
|
|
30
|
-
|
|
31
|
-
setFoundEntities: () => undefined,
|
|
32
|
-
setIsInitialLoad: () => undefined,
|
|
30
|
+
dispatchCounts: () => undefined,
|
|
33
31
|
});
|
|
34
32
|
|
|
35
33
|
// Provider component props
|
|
@@ -45,18 +43,17 @@ export const PaginatedTableProvider = ({
|
|
|
45
43
|
initialState = {},
|
|
46
44
|
noBatching,
|
|
47
45
|
}: PaginatedTableStateProviderProps) => {
|
|
48
|
-
// Use individual state variables for each field
|
|
49
46
|
const [sortParams, setSortParams] = React.useState<PaginatedTableState['sortParams']>(
|
|
50
47
|
initialState.sortParams ?? defaultTableState.sortParams,
|
|
51
48
|
);
|
|
52
|
-
const [totalEntities,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
const [{totalEntities, foundEntities, isInitialLoad}, dispatchCounts] = React.useReducer(
|
|
50
|
+
tableCountsReducer,
|
|
51
|
+
{
|
|
52
|
+
totalEntities: initialState.totalEntities ?? defaultTableState.totalEntities,
|
|
53
|
+
foundEntities: initialState.foundEntities ?? defaultTableState.foundEntities,
|
|
54
|
+
isInitialLoad: initialState.isInitialLoad ?? defaultTableState.isInitialLoad,
|
|
55
|
+
hasLoadedData: initialState.isInitialLoad === false,
|
|
56
|
+
},
|
|
60
57
|
);
|
|
61
58
|
|
|
62
59
|
// Construct tableState from individual state variables
|
|
@@ -70,15 +67,13 @@ export const PaginatedTableProvider = ({
|
|
|
70
67
|
[sortParams, totalEntities, foundEntities, isInitialLoad],
|
|
71
68
|
);
|
|
72
69
|
|
|
73
|
-
// Create the context value with the constructed tableState and
|
|
70
|
+
// Create the context value with the constructed tableState and its update functions
|
|
74
71
|
const contextValue = React.useMemo(
|
|
75
72
|
() => ({
|
|
76
73
|
tableState,
|
|
77
74
|
noBatching,
|
|
78
75
|
setSortParams,
|
|
79
|
-
|
|
80
|
-
setFoundEntities,
|
|
81
|
-
setIsInitialLoad,
|
|
76
|
+
dispatchCounts,
|
|
82
77
|
}),
|
|
83
78
|
[tableState, noBatching],
|
|
84
79
|
);
|
|
@@ -42,7 +42,7 @@ interface TableChunkProps<T, F> {
|
|
|
42
42
|
onRowClick?: OnRowClick<T>;
|
|
43
43
|
renderErrorMessage?: RenderErrorMessage;
|
|
44
44
|
renderEmptyDataMessage?: RenderEmptyDataMessage;
|
|
45
|
-
onDataFetched: (data
|
|
45
|
+
onDataFetched: (data: PaginatedTableData<T>) => void;
|
|
46
46
|
|
|
47
47
|
keepCache?: boolean;
|
|
48
48
|
}
|
|
@@ -104,8 +104,9 @@ export const TableChunk = typedMemo(function TableChunk<T, F>({
|
|
|
104
104
|
};
|
|
105
105
|
}, [shouldFetch, isTimeoutActive]);
|
|
106
106
|
|
|
107
|
-
React.
|
|
107
|
+
React.useLayoutEffect(() => {
|
|
108
108
|
if (currentData) {
|
|
109
|
+
// Consumers derive row dimensions from the response before loaded rows are painted.
|
|
109
110
|
onDataFetched({
|
|
110
111
|
...currentData,
|
|
111
112
|
data: currentData.data as T[],
|
|
@@ -30,7 +30,7 @@ export interface TableChunksRendererProps<T, F> {
|
|
|
30
30
|
onRowClick?: OnRowClick<T>;
|
|
31
31
|
renderErrorMessage?: RenderErrorMessage;
|
|
32
32
|
renderEmptyDataMessage?: RenderEmptyDataMessage;
|
|
33
|
-
onDataFetched: (data
|
|
33
|
+
onDataFetched: (data: PaginatedTableData<T>) => void;
|
|
34
34
|
onActiveChunkOffsetsChange: (offsets: number[]) => void;
|
|
35
35
|
keepCache: boolean;
|
|
36
36
|
fetchOverscan?: number;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
2
|
+
|
|
3
|
+
import type {getTableChunkQueryParams} from './getTableChunkQueryParams';
|
|
4
|
+
import type {PaginatedTableState} from './types';
|
|
5
|
+
|
|
6
|
+
type TableQuery = Omit<ReturnType<typeof getTableChunkQueryParams>, 'offset' | 'fetchData'>;
|
|
7
|
+
|
|
8
|
+
export interface TableCountsState
|
|
9
|
+
extends Pick<PaginatedTableState, 'totalEntities' | 'foundEntities' | 'isInitialLoad'> {
|
|
10
|
+
query?: TableQuery;
|
|
11
|
+
hasLoadedData: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type TableCountsAction =
|
|
15
|
+
| {type: 'initialize'; query: TableQuery; initialEntitiesCount?: number}
|
|
16
|
+
| {type: 'dataReceived'; query: TableQuery; total: number; found: number};
|
|
17
|
+
|
|
18
|
+
export function tableCountsReducer(
|
|
19
|
+
state: TableCountsState,
|
|
20
|
+
action: TableCountsAction,
|
|
21
|
+
): TableCountsState {
|
|
22
|
+
// Cached chunks can report their data before the table's initialization effect.
|
|
23
|
+
if (
|
|
24
|
+
action.type === 'initialize' &&
|
|
25
|
+
isEqual(state.query, action.query) &&
|
|
26
|
+
!state.isInitialLoad
|
|
27
|
+
) {
|
|
28
|
+
return state;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let nextState: TableCountsState;
|
|
32
|
+
if (action.type === 'dataReceived') {
|
|
33
|
+
nextState = {
|
|
34
|
+
query: action.query,
|
|
35
|
+
totalEntities: action.total,
|
|
36
|
+
foundEntities: action.found,
|
|
37
|
+
isInitialLoad: false,
|
|
38
|
+
hasLoadedData: true,
|
|
39
|
+
};
|
|
40
|
+
} else {
|
|
41
|
+
// Keep the virtualized table's size until the next query returns its actual counts.
|
|
42
|
+
nextState = {...state, query: action.query, isInitialLoad: true};
|
|
43
|
+
if (!state.hasLoadedData) {
|
|
44
|
+
nextState.totalEntities = action.initialEntitiesCount ?? 0;
|
|
45
|
+
nextState.foundEntities = action.initialEntitiesCount ?? 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return isEqual(state, nextState) ? state : nextState;
|
|
50
|
+
}
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
} from '../../utils/disks/displayState';
|
|
14
14
|
import {getDefaultDiskDisplayState} from '../../utils/disks/displayState';
|
|
15
15
|
import {getDiskBarTone} from '../../utils/disks/getDiskBarTone';
|
|
16
|
+
import {formatPDiskType} from '../../utils/disks/getPDiskType';
|
|
16
17
|
import {getVDiskStatusIcon} from '../../utils/disks/helpers';
|
|
17
18
|
import type {PreparedVDisk} from '../../utils/disks/types';
|
|
18
19
|
import {isNumeric} from '../../utils/utils';
|
|
@@ -162,7 +163,10 @@ function getAllModeAccessibleName(data: PreparedVDisk, hasIssues: boolean | unde
|
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
function getAccessibleName(
|
|
166
|
+
function getAccessibleName(
|
|
167
|
+
data: PreparedVDisk,
|
|
168
|
+
{mode, allMode, isNoData, driveType}: VDiskDisplayState,
|
|
169
|
+
) {
|
|
166
170
|
if (!mode) {
|
|
167
171
|
return undefined;
|
|
168
172
|
}
|
|
@@ -176,13 +180,24 @@ function getAccessibleName(data: PreparedVDisk, {mode, allMode, isNoData}: VDisk
|
|
|
176
180
|
nodeId: data.NodeId ?? noData,
|
|
177
181
|
});
|
|
178
182
|
if (isNoData) {
|
|
179
|
-
|
|
183
|
+
const hasVDiskWhiteboardData = data.HasWhiteboardData ?? Boolean(data.VDiskId);
|
|
184
|
+
diskName = i18n(
|
|
185
|
+
mode === 'driveType' && hasVDiskWhiteboardData
|
|
186
|
+
? 'context_pdisk-no-whiteboard'
|
|
187
|
+
: 'context_vdisk-no-whiteboard',
|
|
188
|
+
{disk: diskName, noData},
|
|
189
|
+
);
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
const {CapacityAlert, FrontQueues, SatisfactionRank, Replicated} = isNoData ? {} : data;
|
|
183
193
|
const {FreshRank, LevelRank} = SatisfactionRank ?? {};
|
|
184
194
|
|
|
185
195
|
switch (mode) {
|
|
196
|
+
case 'driveType':
|
|
197
|
+
return i18n('context_drive-type-accessible-name', {
|
|
198
|
+
disk: diskName,
|
|
199
|
+
driveType: formatPDiskType(driveType) || noData,
|
|
200
|
+
});
|
|
186
201
|
case 'state':
|
|
187
202
|
return i18n('context_state-accessible-name', {
|
|
188
203
|
disk: diskName,
|
|
@@ -230,6 +245,7 @@ export interface VDiskProps {
|
|
|
230
245
|
popupOffset?: PopupProps['offset'];
|
|
231
246
|
withOpaqueBackground?: boolean;
|
|
232
247
|
getDisplayState?: VDiskDisplayStateGetter;
|
|
248
|
+
hidePDiskInPopup?: boolean;
|
|
233
249
|
}
|
|
234
250
|
|
|
235
251
|
export const VDisk = ({
|
|
@@ -252,6 +268,7 @@ export const VDisk = ({
|
|
|
252
268
|
popupOffset = DEFAULT_POPUP_OFFSET,
|
|
253
269
|
withOpaqueBackground,
|
|
254
270
|
getDisplayState,
|
|
271
|
+
hidePDiskInPopup,
|
|
255
272
|
}: VDiskProps) => {
|
|
256
273
|
const getVDiskLink = useVDiskPagePath();
|
|
257
274
|
const vDiskPath = getVDiskLink({nodeId: data.NodeId, vDiskId: data.StringifiedId});
|
|
@@ -285,7 +302,7 @@ export const VDisk = ({
|
|
|
285
302
|
indicatorClassName,
|
|
286
303
|
iconGroupSize,
|
|
287
304
|
iconSize,
|
|
288
|
-
isDonor,
|
|
305
|
+
isDonor: mode !== 'driveType' && isDonor,
|
|
289
306
|
placement: iconPlacement,
|
|
290
307
|
severity,
|
|
291
308
|
withIcon,
|
|
@@ -307,8 +324,9 @@ export const VDisk = ({
|
|
|
307
324
|
/>
|
|
308
325
|
) : null;
|
|
309
326
|
const tone = getDiskBarTone({
|
|
327
|
+
driveType: displayState.driveType,
|
|
310
328
|
severity,
|
|
311
|
-
isDonor,
|
|
329
|
+
isDonor: mode !== 'driveType' && isDonor,
|
|
312
330
|
showIndicator,
|
|
313
331
|
indicator: icon,
|
|
314
332
|
isNoData,
|
|
@@ -319,7 +337,12 @@ export const VDisk = ({
|
|
|
319
337
|
showPopup={showPopup}
|
|
320
338
|
onShowPopup={onShowPopup}
|
|
321
339
|
onHidePopup={onHidePopup}
|
|
322
|
-
renderPopupContent={({onClose}) =>
|
|
340
|
+
renderPopupContent={({onClose}) => (
|
|
341
|
+
<VDiskPopup
|
|
342
|
+
data={hidePDiskInPopup ? {...data, PDisk: undefined} : data}
|
|
343
|
+
onClose={onClose}
|
|
344
|
+
/>
|
|
345
|
+
)}
|
|
323
346
|
offset={popupOffset}
|
|
324
347
|
delayClose={delayClose}
|
|
325
348
|
delayOpen={delayOpen}
|
|
@@ -8,7 +8,8 @@ import {Stack} from '../Stack/Stack';
|
|
|
8
8
|
import type {VDiskProps} from './VDisk';
|
|
9
9
|
import {VDisk} from './VDisk';
|
|
10
10
|
|
|
11
|
-
interface VDiskWithDonorsStackProps
|
|
11
|
+
interface VDiskWithDonorsStackProps
|
|
12
|
+
extends Omit<VDiskProps, 'withOpaqueBackground' | 'hidePDiskInPopup'> {
|
|
12
13
|
data?: PreparedVDisk;
|
|
13
14
|
className?: string;
|
|
14
15
|
stackClassName?: string;
|
|
@@ -17,6 +18,7 @@ interface VDiskWithDonorsStackProps extends Omit<VDiskProps, 'withOpaqueBackgrou
|
|
|
17
18
|
progressBarClassName?: string;
|
|
18
19
|
renderContent?: boolean;
|
|
19
20
|
placeholderProps?: React.HTMLAttributes<HTMLDivElement>;
|
|
21
|
+
hideMainPDiskInPopup?: boolean;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const diskInStackPlacement: PopupPlacement = ['left', 'right'];
|
|
@@ -29,6 +31,7 @@ export function VDiskWithDonorsStack({
|
|
|
29
31
|
stackClassName,
|
|
30
32
|
withIcon,
|
|
31
33
|
compact,
|
|
34
|
+
hideMainPDiskInPopup,
|
|
32
35
|
highlightedVDisk,
|
|
33
36
|
setHighlightedVDisk,
|
|
34
37
|
showPopup: _showPopup,
|
|
@@ -81,6 +84,7 @@ export function VDiskWithDonorsStack({
|
|
|
81
84
|
const mainVDiskProps: Partial<VDiskProps> = {
|
|
82
85
|
...restProps,
|
|
83
86
|
compact,
|
|
87
|
+
hidePDiskInPopup: hideMainPDiskInPopup,
|
|
84
88
|
withIcon,
|
|
85
89
|
showPopup: isHighlighted,
|
|
86
90
|
highlighted: isHighlighted,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"context_vdisk": "VDisk {{vdiskId}} on node {{nodeId}}",
|
|
4
4
|
"context_donor-vdisk": "Donor VDisk {{vdiskId}} on node {{nodeId}}",
|
|
5
5
|
"context_vdisk-no-whiteboard": "{{disk}}. Whiteboard: {{noData}}",
|
|
6
|
+
"context_pdisk-no-whiteboard": "{{disk}}. PDisk Whiteboard: {{noData}}",
|
|
6
7
|
"context_state-accessible-name": "{{disk}}. State: {{state}}. Replication: {{replication}}.",
|
|
7
8
|
"context_space-accessible-name": "{{disk}}. Capacity alert: {{capacityAlert}}.",
|
|
8
9
|
"context_front-queues-accessible-name": "{{disk}}. Front queues: {{frontQueues}}.",
|
|
@@ -15,5 +16,6 @@
|
|
|
15
16
|
"context_all-mode-health-issues": "issues detected",
|
|
16
17
|
"context_all-mode-replication-complete": "complete",
|
|
17
18
|
"context_all-mode-replication-in-progress": "in progress",
|
|
18
|
-
"context_all-mode-accessible-name": "VDisk {{vdiskId}}. Health: {{health}}. State: {{state}}. Replication: {{replication}}. Capacity alert: {{capacityAlert}}. Front queues: {{frontQueues}}. Fresh compaction: {{freshCompaction}}. Level compaction: {{levelCompaction}}. Allocated: {{allocatedPercent}}."
|
|
19
|
+
"context_all-mode-accessible-name": "VDisk {{vdiskId}}. Health: {{health}}. State: {{state}}. Replication: {{replication}}. Capacity alert: {{capacityAlert}}. Front queues: {{frontQueues}}. Fresh compaction: {{freshCompaction}}. Level compaction: {{levelCompaction}}. Allocated: {{allocatedPercent}}.",
|
|
20
|
+
"context_drive-type-accessible-name": "{{disk}}. Drive type: {{driveType}}."
|
|
19
21
|
}
|
|
@@ -66,9 +66,6 @@ const VDiskItem = React.memo(function VDiskItem({
|
|
|
66
66
|
renderContent,
|
|
67
67
|
placeholderProps,
|
|
68
68
|
}: DisksItemProps) {
|
|
69
|
-
// Do not show PDisk popup for VDisk
|
|
70
|
-
const vDiskToShow = React.useMemo(() => ({...vDisk, PDisk: undefined}), [vDisk]);
|
|
71
|
-
|
|
72
69
|
const style: React.CSSProperties = isAllVDisksLayout
|
|
73
70
|
? {width: ALL_VDISK_WIDTH, flexBasis: ALL_VDISK_WIDTH}
|
|
74
71
|
: {width: compactVDiskWidth, flexBasis: compactVDiskWidth};
|
|
@@ -92,7 +89,8 @@ const VDiskItem = React.memo(function VDiskItem({
|
|
|
92
89
|
<VDiskWithDonorsStack
|
|
93
90
|
renderContent={renderContent}
|
|
94
91
|
placeholderProps={placeholderProps}
|
|
95
|
-
data={
|
|
92
|
+
data={vDisk}
|
|
93
|
+
hideMainPDiskInPopup
|
|
96
94
|
compact={!isAllVDisksLayout}
|
|
97
95
|
withIcon={withIcon}
|
|
98
96
|
inactive={inactive}
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
} from '../../../utils/disks/displayState';
|
|
21
21
|
import {getDefaultPDiskDisplayState} from '../../../utils/disks/displayState';
|
|
22
22
|
import {getDiskBarTone} from '../../../utils/disks/getDiskBarTone';
|
|
23
|
+
import {formatPDiskType} from '../../../utils/disks/getPDiskType';
|
|
23
24
|
import {getPDiskId, getVDiskStatusIcon} from '../../../utils/disks/helpers';
|
|
24
25
|
import type {PreparedPDisk} from '../../../utils/disks/types';
|
|
25
26
|
import {isNumeric} from '../../../utils/utils';
|
|
@@ -78,7 +79,9 @@ function getPDiskContent({
|
|
|
78
79
|
type={
|
|
79
80
|
<React.Fragment>
|
|
80
81
|
{showNoDataLabel ? barContent : null}
|
|
81
|
-
<DiskBarLabel>
|
|
82
|
+
<DiskBarLabel>
|
|
83
|
+
{formatPDiskType(data.Type) || EMPTY_DATA_PLACEHOLDER}
|
|
84
|
+
</DiskBarLabel>
|
|
82
85
|
</React.Fragment>
|
|
83
86
|
}
|
|
84
87
|
/>
|
|
@@ -191,7 +194,7 @@ function getAllModeAccessibleName(
|
|
|
191
194
|
|
|
192
195
|
function getAccessibleName(
|
|
193
196
|
data: PreparedPDisk,
|
|
194
|
-
{mode, allMode, isNoData, allocatedPercent}: PDiskDisplayState,
|
|
197
|
+
{mode, allMode, isNoData, allocatedPercent, driveType}: PDiskDisplayState,
|
|
195
198
|
) {
|
|
196
199
|
if (!mode) {
|
|
197
200
|
return undefined;
|
|
@@ -208,6 +211,11 @@ function getAccessibleName(
|
|
|
208
211
|
const {State, Device, Realtime} = isNoData ? {} : data;
|
|
209
212
|
|
|
210
213
|
switch (mode) {
|
|
214
|
+
case 'driveType':
|
|
215
|
+
return i18n('context_drive-type-accessible-name', {
|
|
216
|
+
disk: diskName,
|
|
217
|
+
driveType: formatPDiskType(driveType) || noData,
|
|
218
|
+
});
|
|
211
219
|
case 'state':
|
|
212
220
|
return i18n('context_state-accessible-name', {disk: diskName, state: State || noData});
|
|
213
221
|
case 'space':
|
|
@@ -325,6 +333,7 @@ export const PDisk = ({
|
|
|
325
333
|
});
|
|
326
334
|
|
|
327
335
|
const tone = getDiskBarTone({
|
|
336
|
+
driveType: displayState.driveType,
|
|
328
337
|
severity: displayState.severity,
|
|
329
338
|
showIndicator,
|
|
330
339
|
indicator: displayState.icon,
|
|
@@ -17,6 +17,7 @@ function getVDiskOptions(): ExpertModeOption<VDisksGroupByValue>[] {
|
|
|
17
17
|
{value: VDisksGroupBy.Space, content: i18n('value_space')},
|
|
18
18
|
{value: VDisksGroupBy.FrontQueues, content: i18n('value_front-queues')},
|
|
19
19
|
{value: VDisksGroupBy.Compaction, content: i18n('value_compaction')},
|
|
20
|
+
{value: VDisksGroupBy.DriveType, content: i18n('value_drive-type')},
|
|
20
21
|
{value: VDisksGroupBy.All, content: i18n('value_all')},
|
|
21
22
|
];
|
|
22
23
|
}
|
|
@@ -29,6 +30,7 @@ function getPDiskOptions(): ExpertModeOption<PDisksGroupByValue>[] {
|
|
|
29
30
|
{value: PDisksGroupBy.Decommit, content: i18n('value_pdisks-decommit')},
|
|
30
31
|
{value: PDisksGroupBy.Maintenance, content: i18n('value_pdisks-maintenance')},
|
|
31
32
|
{value: PDisksGroupBy.Device, content: i18n('value_pdisks-device')},
|
|
33
|
+
{value: PDisksGroupBy.DriveType, content: i18n('value_drive-type')},
|
|
32
34
|
{value: PDisksGroupBy.All, content: i18n('value_pdisks-all')},
|
|
33
35
|
];
|
|
34
36
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {Flex, Label} from '@gravity-ui/uikit';
|
|
2
|
+
|
|
3
|
+
import i18n from '../i18n';
|
|
4
|
+
|
|
5
|
+
export function DriveTypeLegend() {
|
|
6
|
+
return (
|
|
7
|
+
<Flex gap={2} alignItems="center" wrap="wrap">
|
|
8
|
+
<Label size="xs" theme="normal">
|
|
9
|
+
{i18n('value_ssd')}
|
|
10
|
+
</Label>
|
|
11
|
+
<Label size="xs" theme="utility">
|
|
12
|
+
{i18n('value_hdd')}
|
|
13
|
+
</Label>
|
|
14
|
+
<Label size="xs" theme="info">
|
|
15
|
+
{i18n('value_nvme')}
|
|
16
|
+
</Label>
|
|
17
|
+
<Label size="xs" theme="unknown">
|
|
18
|
+
{i18n('value_no-data')}
|
|
19
|
+
</Label>
|
|
20
|
+
</Flex>
|
|
21
|
+
);
|
|
22
|
+
}
|