ydb-embedded-ui 4.17.0 → 4.19.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +30 -0
- package/dist/components/FullNodeViewer/FullNodeViewer.scss +1 -1
- package/dist/components/FullNodeViewer/FullNodeViewer.tsx +15 -6
- package/dist/components/InfoViewer/formatters/common.ts +1 -1
- package/dist/components/InfoViewer/formatters/pqGroup.ts +1 -1
- package/dist/components/InfoViewer/formatters/table.ts +6 -1
- package/dist/components/ProgressViewer/ProgressViewer.tsx +105 -0
- package/dist/components/TooltipsContent/TabletTooltipContent/TabletTooltipContent.tsx +1 -1
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +3 -1
- package/dist/containers/Authentication/Authentication.tsx +14 -4
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +2 -2
- package/dist/containers/Heatmap/Heatmap.tsx +1 -1
- package/dist/containers/Heatmap/Histogram/Histogram.js +1 -1
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +2 -2
- package/dist/containers/Node/NodeStructure/Vdisk.tsx +5 -2
- package/dist/containers/Nodes/getNodesColumns.tsx +3 -2
- package/dist/containers/Storage/PDisk/PDisk.tsx +1 -1
- package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +2 -2
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -232
- package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.tsx +278 -0
- package/dist/containers/Storage/VDisk/VDisk.tsx +1 -1
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +1 -1
- package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +1 -1
- package/dist/containers/Tablet/TabletTable/TabletTable.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Consumers/TopicStats/ConsumersTopicStats.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +2 -3
- package/dist/containers/Tenant/Diagnostics/TenantOverview/OldTenantOverview.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +22 -6
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.scss +41 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TenantStorage.tsx +68 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx +76 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx +105 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +2 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +2 -0
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +1 -1
- package/dist/containers/Tenants/Tenants.tsx +5 -1
- package/dist/containers/UserSettings/i18n/en.json +1 -1
- package/dist/containers/UserSettings/i18n/ru.json +1 -1
- package/dist/containers/UserSettings/settings.ts +2 -2
- package/dist/containers/Versions/NodesTable/NodesTable.tsx +3 -2
- package/dist/services/api.ts +1 -1
- package/dist/store/reducers/clusterNodes/clusterNodes.tsx +1 -1
- package/dist/store/reducers/index.ts +4 -0
- package/dist/store/reducers/node/selectors.ts +1 -1
- package/dist/store/reducers/nodes/selectors.ts +1 -1
- package/dist/store/reducers/nodes/types.ts +1 -1
- package/dist/store/reducers/nodes/utils.ts +1 -1
- package/dist/store/reducers/settings/settings.ts +4 -4
- package/dist/store/reducers/storage/types.ts +1 -1
- package/dist/store/reducers/storage/utils.ts +21 -12
- package/dist/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts +93 -0
- package/dist/store/reducers/tenantOverview/executeTopTables/types.ts +14 -0
- package/dist/store/reducers/tenantOverview/topStorageGroups/topStorageGroups.ts +98 -0
- package/dist/store/reducers/tenantOverview/topStorageGroups/types.ts +29 -0
- package/dist/store/reducers/tenantOverview/topStorageGroups/utils.ts +20 -0
- package/dist/store/reducers/tenants/utils.ts +30 -20
- package/dist/styles/constants.scss +4 -0
- package/dist/types/additionalProps.ts +1 -1
- package/dist/types/api/storage.ts +1 -1
- package/dist/types/api/tenant.ts +21 -8
- package/dist/types/api/vdisk.ts +1 -1
- package/dist/utils/bytesParsers/__test__/formatBytes.test.ts +10 -1
- package/dist/utils/bytesParsers/formatBytes.ts +3 -3
- package/dist/utils/constants.ts +10 -1
- package/dist/utils/dataFormatters/__test__/roundToSignificant.test.ts +22 -0
- package/dist/utils/dataFormatters/dataFormatters.ts +150 -0
- package/dist/utils/dataFormatters/i18n/en.json +3 -0
- package/dist/utils/dataFormatters/i18n/ru.json +3 -0
- package/dist/utils/index.js +0 -102
- package/package.json +1 -1
- package/dist/components/ProgressViewer/ProgressViewer.js +0 -92
- package/dist/utils/formatCPU/formatCPU.ts +0 -20
- package/dist/utils/formatCPU/i18n/en.json +0 -3
- package/dist/utils/formatCPU/i18n/ru.json +0 -3
- /package/dist/utils/{formatCPU → dataFormatters}/i18n/index.ts +0 -0
@@ -1,25 +1,12 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
|
-
|
3
1
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
4
|
-
import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
5
2
|
|
6
|
-
import type {ValueOf} from '../../../types/common';
|
7
3
|
import type {NodesMap} from '../../../types/store/nodesList';
|
8
4
|
import type {PreparedStorageGroup, VisibleEntities} from '../../../store/reducers/storage/types';
|
9
5
|
import type {HandleSort} from '../../../utils/hooks/useTableSort';
|
10
|
-
|
11
6
|
import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
12
|
-
import {
|
13
|
-
import {stringifyVdiskId} from '../../../utils';
|
14
|
-
import {getUsage, isFullVDiskData, isSortableStorageProperty} from '../../../utils/storage';
|
15
|
-
|
16
|
-
import shieldIcon from '../../../assets/icons/shield.svg';
|
17
|
-
import {Stack} from '../../../components/Stack/Stack';
|
18
|
-
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
19
|
-
|
7
|
+
import {isSortableStorageProperty} from '../../../utils/storage';
|
20
8
|
import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
|
21
|
-
import {
|
22
|
-
import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
|
9
|
+
import {getStorageGroupsColumns} from './getStorageGroupsColumns';
|
23
10
|
|
24
11
|
import i18n from './i18n';
|
25
12
|
import './StorageGroups.scss';
|
@@ -39,8 +26,6 @@ const TableColumnsIds = {
|
|
39
26
|
Degraded: 'Degraded',
|
40
27
|
} as const;
|
41
28
|
|
42
|
-
type TableColumnId = ValueOf<typeof TableColumnsIds>;
|
43
|
-
|
44
29
|
interface StorageGroupsProps {
|
45
30
|
data: PreparedStorageGroup[];
|
46
31
|
nodes?: NodesMap;
|
@@ -51,23 +36,6 @@ interface StorageGroupsProps {
|
|
51
36
|
handleSort?: HandleSort;
|
52
37
|
}
|
53
38
|
|
54
|
-
const tableColumnsNames: Record<TableColumnId, string> = {
|
55
|
-
PoolName: 'Pool Name',
|
56
|
-
Kind: 'Type',
|
57
|
-
Erasure: 'Erasure',
|
58
|
-
GroupId: 'Group ID',
|
59
|
-
Used: 'Used',
|
60
|
-
Limit: 'Limit',
|
61
|
-
UsedSpaceFlag: 'Space',
|
62
|
-
Usage: 'Usage',
|
63
|
-
Read: 'Read',
|
64
|
-
Write: 'Write',
|
65
|
-
VDisks: 'VDisks',
|
66
|
-
Degraded: 'Degraded',
|
67
|
-
};
|
68
|
-
|
69
|
-
const b = cn('global-storage-groups');
|
70
|
-
|
71
39
|
export function StorageGroups({
|
72
40
|
data,
|
73
41
|
tableSettings,
|
@@ -77,204 +45,7 @@ export function StorageGroups({
|
|
77
45
|
sort,
|
78
46
|
handleSort,
|
79
47
|
}: StorageGroupsProps) {
|
80
|
-
const rawColumns: Column<PreparedStorageGroup>[] =
|
81
|
-
{
|
82
|
-
name: TableColumnsIds.PoolName,
|
83
|
-
header: tableColumnsNames[TableColumnsIds.PoolName],
|
84
|
-
width: 250,
|
85
|
-
render: ({row}) => {
|
86
|
-
const splitted = row.PoolName?.split('/');
|
87
|
-
return (
|
88
|
-
<div className={b('pool-name-wrapper')}>
|
89
|
-
{splitted && (
|
90
|
-
<Popover
|
91
|
-
content={row.PoolName}
|
92
|
-
placement={['right']}
|
93
|
-
behavior={PopoverBehavior.Immediate}
|
94
|
-
>
|
95
|
-
<span className={b('pool-name')}>
|
96
|
-
{splitted[splitted.length - 1]}
|
97
|
-
</span>
|
98
|
-
</Popover>
|
99
|
-
)}
|
100
|
-
</div>
|
101
|
-
);
|
102
|
-
},
|
103
|
-
align: DataTable.LEFT,
|
104
|
-
},
|
105
|
-
{
|
106
|
-
name: TableColumnsIds.Kind,
|
107
|
-
header: tableColumnsNames[TableColumnsIds.Kind],
|
108
|
-
// prettier-ignore
|
109
|
-
render: ({row}) => (
|
110
|
-
<>
|
111
|
-
<Label>{row.Kind || '—'}</Label>
|
112
|
-
{' '}
|
113
|
-
{row.Encryption && (
|
114
|
-
<Popover
|
115
|
-
content={i18n('encrypted')}
|
116
|
-
placement="right"
|
117
|
-
behavior={PopoverBehavior.Immediate}
|
118
|
-
>
|
119
|
-
<Label>
|
120
|
-
<Icon data={shieldIcon} />
|
121
|
-
</Label>
|
122
|
-
</Popover>
|
123
|
-
)}
|
124
|
-
</>
|
125
|
-
),
|
126
|
-
},
|
127
|
-
{
|
128
|
-
name: TableColumnsIds.Erasure,
|
129
|
-
header: tableColumnsNames[TableColumnsIds.Erasure],
|
130
|
-
render: ({row}) => (row.ErasureSpecies ? row.ErasureSpecies : '-'),
|
131
|
-
align: DataTable.LEFT,
|
132
|
-
},
|
133
|
-
{
|
134
|
-
name: TableColumnsIds.Degraded,
|
135
|
-
header: tableColumnsNames[TableColumnsIds.Degraded],
|
136
|
-
width: 100,
|
137
|
-
render: ({row}) =>
|
138
|
-
row.Degraded ? (
|
139
|
-
<Label theme={getDegradedSeverity(row)}>Degraded: {row.Degraded}</Label>
|
140
|
-
) : (
|
141
|
-
'-'
|
142
|
-
),
|
143
|
-
align: DataTable.LEFT,
|
144
|
-
defaultOrder: DataTable.DESCENDING,
|
145
|
-
},
|
146
|
-
{
|
147
|
-
name: TableColumnsIds.Usage,
|
148
|
-
header: tableColumnsNames[TableColumnsIds.Usage],
|
149
|
-
width: 100,
|
150
|
-
render: ({row}) => {
|
151
|
-
// without a limit the usage can be evaluated as 0,
|
152
|
-
// but the absence of a value is more clear
|
153
|
-
return row.Limit ? (
|
154
|
-
<Label
|
155
|
-
theme={getUsageSeverityForStorageGroup(row.Usage)}
|
156
|
-
className={b('usage-label', {overload: row.Usage >= 90})}
|
157
|
-
>
|
158
|
-
{row.Usage}%
|
159
|
-
</Label>
|
160
|
-
) : (
|
161
|
-
'-'
|
162
|
-
);
|
163
|
-
},
|
164
|
-
// without a limit exclude usage from sort to display at the bottom
|
165
|
-
sortAccessor: (row) => (row.Limit ? getUsage(row) : null),
|
166
|
-
align: DataTable.LEFT,
|
167
|
-
},
|
168
|
-
{
|
169
|
-
name: TableColumnsIds.GroupId,
|
170
|
-
header: tableColumnsNames[TableColumnsIds.GroupId],
|
171
|
-
width: 130,
|
172
|
-
render: ({row}) => {
|
173
|
-
return <span className={b('group-id')}>{row.GroupID}</span>;
|
174
|
-
},
|
175
|
-
sortAccessor: (row) => Number(row.GroupID),
|
176
|
-
align: DataTable.RIGHT,
|
177
|
-
},
|
178
|
-
{
|
179
|
-
name: TableColumnsIds.Used,
|
180
|
-
header: tableColumnsNames[TableColumnsIds.Used],
|
181
|
-
width: 100,
|
182
|
-
render: ({row}) => {
|
183
|
-
return bytesToGB(row.Used, true);
|
184
|
-
},
|
185
|
-
align: DataTable.RIGHT,
|
186
|
-
},
|
187
|
-
{
|
188
|
-
name: TableColumnsIds.Limit,
|
189
|
-
header: tableColumnsNames[TableColumnsIds.Limit],
|
190
|
-
width: 100,
|
191
|
-
render: ({row}) => {
|
192
|
-
return bytesToGB(row.Limit);
|
193
|
-
},
|
194
|
-
align: DataTable.RIGHT,
|
195
|
-
},
|
196
|
-
{
|
197
|
-
name: TableColumnsIds.UsedSpaceFlag,
|
198
|
-
header: tableColumnsNames[TableColumnsIds.UsedSpaceFlag],
|
199
|
-
width: 110,
|
200
|
-
render: ({row}) => {
|
201
|
-
const value = row.UsedSpaceFlag;
|
202
|
-
|
203
|
-
let color = 'Red';
|
204
|
-
|
205
|
-
if (value < 100) {
|
206
|
-
color = 'Green';
|
207
|
-
} else if (value < 10000) {
|
208
|
-
color = 'Yellow';
|
209
|
-
} else if (value < 1000000) {
|
210
|
-
color = 'Orange';
|
211
|
-
}
|
212
|
-
return <EntityStatus status={color} />;
|
213
|
-
},
|
214
|
-
align: DataTable.CENTER,
|
215
|
-
},
|
216
|
-
|
217
|
-
{
|
218
|
-
name: TableColumnsIds.Read,
|
219
|
-
header: tableColumnsNames[TableColumnsIds.Read],
|
220
|
-
width: 100,
|
221
|
-
render: ({row}) => {
|
222
|
-
return row.Read ? bytesToSpeed(row.Read) : '-';
|
223
|
-
},
|
224
|
-
align: DataTable.RIGHT,
|
225
|
-
},
|
226
|
-
{
|
227
|
-
name: TableColumnsIds.Write,
|
228
|
-
header: tableColumnsNames[TableColumnsIds.Write],
|
229
|
-
width: 100,
|
230
|
-
render: ({row}) => {
|
231
|
-
return row.Write ? bytesToSpeed(row.Write) : '-';
|
232
|
-
},
|
233
|
-
align: DataTable.RIGHT,
|
234
|
-
},
|
235
|
-
{
|
236
|
-
name: TableColumnsIds.VDisks,
|
237
|
-
className: b('vdisks-column'),
|
238
|
-
header: tableColumnsNames[TableColumnsIds.VDisks],
|
239
|
-
render: ({row}) => (
|
240
|
-
<div className={b('vdisks-wrapper')}>
|
241
|
-
{row.VDisks?.map((vDisk) => {
|
242
|
-
const donors = vDisk.Donors;
|
243
|
-
|
244
|
-
return donors && donors.length > 0 ? (
|
245
|
-
<Stack
|
246
|
-
className={b('vdisks-item')}
|
247
|
-
key={stringifyVdiskId(vDisk.VDiskId)}
|
248
|
-
>
|
249
|
-
<VDisk data={vDisk} nodes={nodes} />
|
250
|
-
{donors.map((donor) => {
|
251
|
-
const isFullData = isFullVDiskData(donor);
|
252
|
-
|
253
|
-
return (
|
254
|
-
<VDisk
|
255
|
-
data={isFullData ? donor : {...donor, DonorMode: true}}
|
256
|
-
// donor and acceptor are always in the same group
|
257
|
-
nodes={nodes}
|
258
|
-
key={stringifyVdiskId(
|
259
|
-
isFullData ? donor.VDiskId : donor,
|
260
|
-
)}
|
261
|
-
/>
|
262
|
-
);
|
263
|
-
})}
|
264
|
-
</Stack>
|
265
|
-
) : (
|
266
|
-
<div className={b('vdisks-item')} key={stringifyVdiskId(vDisk.VDiskId)}>
|
267
|
-
<VDisk data={vDisk} nodes={nodes} />
|
268
|
-
</div>
|
269
|
-
);
|
270
|
-
})}
|
271
|
-
</div>
|
272
|
-
),
|
273
|
-
align: DataTable.CENTER,
|
274
|
-
sortable: false,
|
275
|
-
width: 900,
|
276
|
-
},
|
277
|
-
];
|
48
|
+
const rawColumns: Column<PreparedStorageGroup>[] = getStorageGroupsColumns(nodes);
|
278
49
|
|
279
50
|
let columns = rawColumns.map((column) => ({
|
280
51
|
...column,
|
@@ -0,0 +1,278 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import DataTable, {type Column} from '@gravity-ui/react-data-table';
|
4
|
+
import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
5
|
+
|
6
|
+
import shieldIcon from '../../../assets/icons/shield.svg';
|
7
|
+
import type {ValueOf} from '../../../types/common';
|
8
|
+
import type {NodesMap} from '../../../types/store/nodesList';
|
9
|
+
import type {PreparedStorageGroup} from '../../../store/reducers/storage/types';
|
10
|
+
import {getUsage, isFullVDiskData} from '../../../utils/storage';
|
11
|
+
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
|
12
|
+
import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters';
|
13
|
+
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
14
|
+
import {Stack} from '../../../components/Stack/Stack';
|
15
|
+
import {VDisk} from '../VDisk';
|
16
|
+
import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
|
17
|
+
import i18n from './i18n';
|
18
|
+
import './StorageGroups.scss';
|
19
|
+
|
20
|
+
const b = cn('global-storage-groups');
|
21
|
+
|
22
|
+
const GROUPS_COLUMNS_IDS = {
|
23
|
+
PoolName: 'PoolName',
|
24
|
+
Kind: 'Kind',
|
25
|
+
Erasure: 'Erasure',
|
26
|
+
GroupId: 'GroupId',
|
27
|
+
Used: 'Used',
|
28
|
+
Limit: 'Limit',
|
29
|
+
Usage: 'Usage',
|
30
|
+
UsedSpaceFlag: 'UsedSpaceFlag',
|
31
|
+
Read: 'Read',
|
32
|
+
Write: 'Write',
|
33
|
+
VDisks: 'VDisks',
|
34
|
+
Degraded: 'Degraded',
|
35
|
+
} as const;
|
36
|
+
|
37
|
+
type GroupsColumns = ValueOf<typeof GROUPS_COLUMNS_IDS>;
|
38
|
+
|
39
|
+
const tableColumnsNames: Record<GroupsColumns, string> = {
|
40
|
+
PoolName: 'Pool Name',
|
41
|
+
Kind: 'Type',
|
42
|
+
Erasure: 'Erasure',
|
43
|
+
GroupId: 'Group ID',
|
44
|
+
Used: 'Used',
|
45
|
+
Limit: 'Limit',
|
46
|
+
UsedSpaceFlag: 'Space',
|
47
|
+
Usage: 'Usage',
|
48
|
+
Read: 'Read',
|
49
|
+
Write: 'Write',
|
50
|
+
VDisks: 'VDisks',
|
51
|
+
Degraded: 'Degraded',
|
52
|
+
};
|
53
|
+
|
54
|
+
const poolNameColumn: Column<PreparedStorageGroup> = {
|
55
|
+
name: GROUPS_COLUMNS_IDS.PoolName,
|
56
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.PoolName],
|
57
|
+
width: 250,
|
58
|
+
render: ({row}) => {
|
59
|
+
const splitted = row.PoolName?.split('/');
|
60
|
+
return (
|
61
|
+
<div className={b('pool-name-wrapper')}>
|
62
|
+
{splitted && (
|
63
|
+
<Popover
|
64
|
+
content={row.PoolName}
|
65
|
+
placement={['right']}
|
66
|
+
behavior={PopoverBehavior.Immediate}
|
67
|
+
>
|
68
|
+
<span className={b('pool-name')}>{splitted[splitted.length - 1]}</span>
|
69
|
+
</Popover>
|
70
|
+
)}
|
71
|
+
</div>
|
72
|
+
);
|
73
|
+
},
|
74
|
+
align: DataTable.LEFT,
|
75
|
+
};
|
76
|
+
|
77
|
+
const kindColumn: Column<PreparedStorageGroup> = {
|
78
|
+
name: GROUPS_COLUMNS_IDS.Kind,
|
79
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Kind],
|
80
|
+
// prettier-ignore
|
81
|
+
render: ({row}) => (
|
82
|
+
<>
|
83
|
+
<Label>{row.Kind || '—'}</Label>
|
84
|
+
{' '}
|
85
|
+
{row.Encryption && (
|
86
|
+
<Popover
|
87
|
+
content={i18n('encrypted')}
|
88
|
+
placement="right"
|
89
|
+
behavior={PopoverBehavior.Immediate}
|
90
|
+
>
|
91
|
+
<Label>
|
92
|
+
<Icon data={shieldIcon} />
|
93
|
+
</Label>
|
94
|
+
</Popover>
|
95
|
+
)}
|
96
|
+
</>
|
97
|
+
),
|
98
|
+
sortable: false,
|
99
|
+
};
|
100
|
+
|
101
|
+
const erasureColumn: Column<PreparedStorageGroup> = {
|
102
|
+
name: GROUPS_COLUMNS_IDS.Erasure,
|
103
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Erasure],
|
104
|
+
render: ({row}) => (row.ErasureSpecies ? row.ErasureSpecies : '-'),
|
105
|
+
align: DataTable.LEFT,
|
106
|
+
sortable: false,
|
107
|
+
};
|
108
|
+
|
109
|
+
const degradedColumn: Column<PreparedStorageGroup> = {
|
110
|
+
name: GROUPS_COLUMNS_IDS.Degraded,
|
111
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Degraded],
|
112
|
+
width: 100,
|
113
|
+
render: ({row}) =>
|
114
|
+
row.Degraded ? (
|
115
|
+
<Label theme={getDegradedSeverity(row)}>Degraded: {row.Degraded}</Label>
|
116
|
+
) : (
|
117
|
+
'-'
|
118
|
+
),
|
119
|
+
align: DataTable.LEFT,
|
120
|
+
defaultOrder: DataTable.DESCENDING,
|
121
|
+
};
|
122
|
+
|
123
|
+
const usageColumn: Column<PreparedStorageGroup> = {
|
124
|
+
name: GROUPS_COLUMNS_IDS.Usage,
|
125
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Usage],
|
126
|
+
width: 100,
|
127
|
+
render: ({row}) => {
|
128
|
+
// without a limit the usage can be evaluated as 0,
|
129
|
+
// but the absence of a value is more clear
|
130
|
+
return row.Limit ? (
|
131
|
+
<Label
|
132
|
+
theme={getUsageSeverityForStorageGroup(row.Usage)}
|
133
|
+
className={b('usage-label', {overload: row.Usage >= 90})}
|
134
|
+
>
|
135
|
+
{row.Usage}%
|
136
|
+
</Label>
|
137
|
+
) : (
|
138
|
+
'-'
|
139
|
+
);
|
140
|
+
},
|
141
|
+
// without a limit exclude usage from sort to display at the bottom
|
142
|
+
sortAccessor: (row) => (row.Limit ? getUsage(row) : null),
|
143
|
+
align: DataTable.LEFT,
|
144
|
+
sortable: false,
|
145
|
+
};
|
146
|
+
|
147
|
+
const groupIdColumn: Column<PreparedStorageGroup> = {
|
148
|
+
name: GROUPS_COLUMNS_IDS.GroupId,
|
149
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.GroupId],
|
150
|
+
width: 130,
|
151
|
+
render: ({row}) => {
|
152
|
+
return <span className={b('group-id')}>{row.GroupID}</span>;
|
153
|
+
},
|
154
|
+
sortAccessor: (row) => Number(row.GroupID),
|
155
|
+
align: DataTable.RIGHT,
|
156
|
+
sortable: false,
|
157
|
+
};
|
158
|
+
|
159
|
+
const usedColumn: Column<PreparedStorageGroup> = {
|
160
|
+
name: GROUPS_COLUMNS_IDS.Used,
|
161
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Used],
|
162
|
+
width: 100,
|
163
|
+
render: ({row}) => {
|
164
|
+
return bytesToGB(row.Used, true);
|
165
|
+
},
|
166
|
+
align: DataTable.RIGHT,
|
167
|
+
sortable: false,
|
168
|
+
};
|
169
|
+
|
170
|
+
const limitColumn: Column<PreparedStorageGroup> = {
|
171
|
+
name: GROUPS_COLUMNS_IDS.Limit,
|
172
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Limit],
|
173
|
+
width: 100,
|
174
|
+
render: ({row}) => {
|
175
|
+
return bytesToGB(row.Limit);
|
176
|
+
},
|
177
|
+
align: DataTable.RIGHT,
|
178
|
+
sortable: false,
|
179
|
+
};
|
180
|
+
|
181
|
+
const usedSpaceFlagColumn: Column<PreparedStorageGroup> = {
|
182
|
+
name: GROUPS_COLUMNS_IDS.UsedSpaceFlag,
|
183
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.UsedSpaceFlag],
|
184
|
+
width: 110,
|
185
|
+
render: ({row}) => {
|
186
|
+
const value = row.UsedSpaceFlag;
|
187
|
+
|
188
|
+
let color = 'Red';
|
189
|
+
|
190
|
+
if (value < 100) {
|
191
|
+
color = 'Green';
|
192
|
+
} else if (value < 10000) {
|
193
|
+
color = 'Yellow';
|
194
|
+
} else if (value < 1000000) {
|
195
|
+
color = 'Orange';
|
196
|
+
}
|
197
|
+
return <EntityStatus status={color} />;
|
198
|
+
},
|
199
|
+
align: DataTable.CENTER,
|
200
|
+
};
|
201
|
+
|
202
|
+
const readColumn: Column<PreparedStorageGroup> = {
|
203
|
+
name: GROUPS_COLUMNS_IDS.Read,
|
204
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Read],
|
205
|
+
width: 100,
|
206
|
+
render: ({row}) => {
|
207
|
+
return row.Read ? bytesToSpeed(row.Read) : '-';
|
208
|
+
},
|
209
|
+
align: DataTable.RIGHT,
|
210
|
+
};
|
211
|
+
|
212
|
+
const writeColumn: Column<PreparedStorageGroup> = {
|
213
|
+
name: GROUPS_COLUMNS_IDS.Write,
|
214
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.Write],
|
215
|
+
width: 100,
|
216
|
+
render: ({row}) => {
|
217
|
+
return row.Write ? bytesToSpeed(row.Write) : '-';
|
218
|
+
},
|
219
|
+
align: DataTable.RIGHT,
|
220
|
+
};
|
221
|
+
|
222
|
+
const getVdiscksColumn = (nodes?: NodesMap): Column<PreparedStorageGroup> => ({
|
223
|
+
name: GROUPS_COLUMNS_IDS.VDisks,
|
224
|
+
className: b('vdisks-column'),
|
225
|
+
header: tableColumnsNames[GROUPS_COLUMNS_IDS.VDisks],
|
226
|
+
render: ({row}) => (
|
227
|
+
<div className={b('vdisks-wrapper')}>
|
228
|
+
{row.VDisks?.map((vDisk) => {
|
229
|
+
const donors = vDisk.Donors;
|
230
|
+
|
231
|
+
return donors && donors.length > 0 ? (
|
232
|
+
<Stack className={b('vdisks-item')} key={stringifyVdiskId(vDisk.VDiskId)}>
|
233
|
+
<VDisk data={vDisk} nodes={nodes} />
|
234
|
+
{donors.map((donor) => {
|
235
|
+
const isFullData = isFullVDiskData(donor);
|
236
|
+
|
237
|
+
return (
|
238
|
+
<VDisk
|
239
|
+
data={isFullData ? donor : {...donor, DonorMode: true}}
|
240
|
+
// donor and acceptor are always in the same group
|
241
|
+
nodes={nodes}
|
242
|
+
key={stringifyVdiskId(isFullData ? donor.VDiskId : donor)}
|
243
|
+
/>
|
244
|
+
);
|
245
|
+
})}
|
246
|
+
</Stack>
|
247
|
+
) : (
|
248
|
+
<div className={b('vdisks-item')} key={stringifyVdiskId(vDisk.VDiskId)}>
|
249
|
+
<VDisk data={vDisk} nodes={nodes} />
|
250
|
+
</div>
|
251
|
+
);
|
252
|
+
})}
|
253
|
+
</div>
|
254
|
+
),
|
255
|
+
align: DataTable.CENTER,
|
256
|
+
width: 900,
|
257
|
+
});
|
258
|
+
|
259
|
+
export const getStorageTopGroupsColumns = (): Column<PreparedStorageGroup>[] => {
|
260
|
+
return [groupIdColumn, kindColumn, erasureColumn, usageColumn, usedColumn, limitColumn];
|
261
|
+
};
|
262
|
+
|
263
|
+
export const getStorageGroupsColumns = (nodes?: NodesMap): Column<PreparedStorageGroup>[] => {
|
264
|
+
return [
|
265
|
+
poolNameColumn,
|
266
|
+
kindColumn,
|
267
|
+
erasureColumn,
|
268
|
+
degradedColumn,
|
269
|
+
usageColumn,
|
270
|
+
groupIdColumn,
|
271
|
+
usedColumn,
|
272
|
+
limitColumn,
|
273
|
+
usedSpaceFlagColumn,
|
274
|
+
readColumn,
|
275
|
+
writeColumn,
|
276
|
+
getVdiscksColumn(nodes),
|
277
|
+
];
|
278
|
+
};
|
@@ -8,7 +8,7 @@ import {InternalLink} from '../../../components/InternalLink';
|
|
8
8
|
import routes, {createHref} from '../../../routes';
|
9
9
|
import {EFlag} from '../../../types/api/enums';
|
10
10
|
import {EVDiskState, TVDiskStateInfo} from '../../../types/api/vdisk';
|
11
|
-
import {stringifyVdiskId} from '../../../utils';
|
11
|
+
import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters';
|
12
12
|
import {isFullVDiskData} from '../../../utils/storage';
|
13
13
|
|
14
14
|
import {STRUCTURE} from '../../Node/NodePages';
|
@@ -9,7 +9,7 @@ import {InfoViewer, InfoViewerItem} from '../../../components/InfoViewer';
|
|
9
9
|
|
10
10
|
import {EFlag} from '../../../types/api/enums';
|
11
11
|
import type {TVDiskStateInfo} from '../../../types/api/vdisk';
|
12
|
-
import {stringifyVdiskId} from '../../../utils';
|
12
|
+
import {stringifyVdiskId} from '../../../utils/dataFormatters/dataFormatters';
|
13
13
|
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
|
14
14
|
import {isFullVDiskData} from '../../../utils/storage';
|
15
15
|
|
@@ -5,7 +5,7 @@ import {Link as UIKitLink} from '@gravity-ui/uikit';
|
|
5
5
|
import {ETabletState, TTabletStateInfo} from '../../../types/api/tablet';
|
6
6
|
import {InfoViewer, InfoViewerItem} from '../../../components/InfoViewer';
|
7
7
|
import routes, {createHref} from '../../../routes';
|
8
|
-
import {calcUptime} from '../../../utils';
|
8
|
+
import {calcUptime} from '../../../utils/dataFormatters/dataFormatters';
|
9
9
|
import {getDefaultNodePath} from '../../Node/NodePages';
|
10
10
|
|
11
11
|
import {b} from '../Tablet';
|
@@ -4,7 +4,7 @@ import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
|
4
4
|
import {InternalLink} from '../../../components/InternalLink/InternalLink';
|
5
5
|
|
6
6
|
import type {ITabletPreparedHistoryItem} from '../../../types/store/tablet';
|
7
|
-
import {calcUptime} from '../../../utils';
|
7
|
+
import {calcUptime} from '../../../utils/dataFormatters/dataFormatters';
|
8
8
|
import {getDefaultNodePath} from '../../Node/NodePages';
|
9
9
|
|
10
10
|
import {b} from '../Tablet';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import block from 'bem-cn-lite';
|
2
2
|
|
3
3
|
import type {IPreparedTopicStats} from '../../../../../types/store/topic';
|
4
|
-
import {formatMsToUptime} from '../../../../../utils';
|
4
|
+
import {formatMsToUptime} from '../../../../../utils/dataFormatters/dataFormatters';
|
5
5
|
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
|
6
6
|
|
7
7
|
import './ConsumersTopicStats.scss';
|
@@ -6,7 +6,7 @@ import type {IPreparedConsumerData} from '../../../../../types/store/topic';
|
|
6
6
|
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
|
7
7
|
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
|
8
8
|
import {InternalLink} from '../../../../../components/InternalLink';
|
9
|
-
import {formatMsToUptime} from '../../../../../utils';
|
9
|
+
import {formatMsToUptime} from '../../../../../utils/dataFormatters/dataFormatters';
|
10
10
|
import routes, {createHref} from '../../../../../routes';
|
11
11
|
|
12
12
|
import {TenantTabsGroups} from '../../../TenantPages';
|
@@ -8,7 +8,7 @@ import type {EPathType} from '../../../../types/api/schema';
|
|
8
8
|
import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
|
9
9
|
import {Icon} from '../../../../components/Icon';
|
10
10
|
import {useSetting} from '../../../../utils/hooks';
|
11
|
-
import {
|
11
|
+
import {DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS} from '../../../../utils/constants';
|
12
12
|
import Overview from '../Overview/Overview';
|
13
13
|
import {Healthcheck} from '../OldHealthcheck';
|
14
14
|
import {TenantOverview} from '../TenantOverview/TenantOverview';
|
@@ -32,7 +32,7 @@ function DetailedOverview(props: DetailedOverviewProps) {
|
|
32
32
|
|
33
33
|
const {currentSchemaPath} = useSelector((state: any) => state.schema);
|
34
34
|
|
35
|
-
const [
|
35
|
+
const [displayMetricsCards] = useSetting(DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS);
|
36
36
|
|
37
37
|
const openModalHandler = () => {
|
38
38
|
setIsModalVisible(true);
|
@@ -59,7 +59,7 @@ function DetailedOverview(props: DetailedOverviewProps) {
|
|
59
59
|
};
|
60
60
|
|
61
61
|
const renderTenantOverview = () => {
|
62
|
-
if (
|
62
|
+
if (displayMetricsCards) {
|
63
63
|
return (
|
64
64
|
<div className={b('section')}>
|
65
65
|
<TenantOverview
|
@@ -8,7 +8,7 @@ import type {
|
|
8
8
|
import type {KeyValueRow} from '../../../../../types/api/query';
|
9
9
|
import {EPathType} from '../../../../../types/api/schema';
|
10
10
|
import {isNumeric} from '../../../../../utils/utils';
|
11
|
-
import {formatBytes, formatNumber} from '../../../../../utils';
|
11
|
+
import {formatBytes, formatNumber} from '../../../../../utils/dataFormatters/dataFormatters';
|
12
12
|
import {formatDurationToShortTimeFormat} from '../../../../../utils/timeParsers';
|
13
13
|
import {formatObject, InfoViewerItem} from '../../../../../components/InfoViewer';
|
14
14
|
import {
|
@@ -11,7 +11,7 @@ import {ResponseError} from '../../../../../components/Errors/ResponseError';
|
|
11
11
|
|
12
12
|
import {useTypedSelector} from '../../../../../utils/hooks';
|
13
13
|
import {formatDurationToShortTimeFormat} from '../../../../../utils/timeParsers';
|
14
|
-
import {formatBps, formatBytes} from '../../../../../utils';
|
14
|
+
import {formatBps, formatBytes} from '../../../../../utils/dataFormatters/dataFormatters';
|
15
15
|
|
16
16
|
import {selectPreparedTopicStats} from '../../../../../store/reducers/topic';
|
17
17
|
|
@@ -4,7 +4,7 @@ import block from 'bem-cn-lite';
|
|
4
4
|
import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
|
5
5
|
import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
|
6
6
|
import {getDefaultNodePath} from '../../../../Node/NodePages';
|
7
|
-
import {formatBytes, formatMsToUptime} from '../../../../../utils';
|
7
|
+
import {formatBytes, formatMsToUptime} from '../../../../../utils/dataFormatters/dataFormatters';
|
8
8
|
import {isNumeric} from '../../../../../utils/utils';
|
9
9
|
|
10
10
|
import {
|