ydb-embedded-ui 4.9.0 → 4.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +7 -4
  3. package/dist/components/EntityStatus/EntityStatus.js +3 -1
  4. package/dist/components/FormattedBytes/FormattedBytes.tsx +10 -0
  5. package/dist/components/FormattedBytes/utils.tsx +13 -0
  6. package/dist/components/FullNodeViewer/FullNodeViewer.tsx +73 -0
  7. package/dist/components/InfoViewer/formatters/table.ts +6 -5
  8. package/dist/components/ProblemFilter/ProblemFilter.tsx +2 -2
  9. package/dist/components/SpeedMultiMeter/SpeedMultiMeter.tsx +4 -4
  10. package/dist/components/TruncatedQuery/{TruncatedQuery.js → TruncatedQuery.tsx} +10 -8
  11. package/dist/containers/AsideNavigation/AsideNavigation.tsx +6 -6
  12. package/dist/containers/Cluster/Cluster.tsx +10 -6
  13. package/dist/containers/Node/Node.tsx +3 -3
  14. package/dist/containers/Nodes/Nodes.tsx +2 -2
  15. package/dist/containers/Storage/PDisk/PDisk.tsx +2 -7
  16. package/dist/containers/Storage/Storage.tsx +240 -0
  17. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +45 -40
  18. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +12 -16
  19. package/dist/containers/Storage/UsageFilter/UsageFilter.scss +1 -0
  20. package/dist/containers/Storage/UsageFilter/UsageFilter.tsx +17 -17
  21. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -3
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -4
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +0 -15
  24. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +10 -3
  25. package/dist/containers/Tenant/{Preview → Query/Preview}/Preview.scss +1 -1
  26. package/dist/containers/Tenant/Query/Preview/Preview.tsx +121 -0
  27. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +1 -1
  28. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +6 -8
  29. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +1 -1
  30. package/dist/containers/Tenant/Query/i18n/en.json +8 -1
  31. package/dist/containers/Tenant/Query/i18n/ru.json +8 -1
  32. package/dist/containers/Tenants/Tenants.tsx +269 -0
  33. package/dist/services/api.ts +8 -3
  34. package/dist/store/reducers/nodes/nodes.ts +4 -4
  35. package/dist/store/reducers/partitions/types.ts +3 -3
  36. package/dist/store/reducers/settings/settings.ts +4 -2
  37. package/dist/store/reducers/settings/types.ts +3 -1
  38. package/dist/store/reducers/storage/selectors.ts +279 -0
  39. package/dist/store/reducers/storage/storage.ts +191 -0
  40. package/dist/store/reducers/storage/types.ts +80 -0
  41. package/dist/store/reducers/tenants/selectors.ts +46 -0
  42. package/dist/store/reducers/tenants/tenants.ts +21 -14
  43. package/dist/store/reducers/tenants/types.ts +20 -5
  44. package/dist/store/reducers/tenants/utils.ts +68 -0
  45. package/dist/types/additionalProps.ts +8 -0
  46. package/dist/types/api/storage.ts +1 -1
  47. package/dist/types/store/topic.ts +3 -3
  48. package/dist/utils/bytesParsers/__test__/formatBytes.test.ts +38 -0
  49. package/dist/utils/bytesParsers/convertBytesObjectToSpeed.ts +2 -2
  50. package/dist/utils/bytesParsers/formatBytes.ts +132 -0
  51. package/dist/utils/bytesParsers/i18n/en.json +1 -0
  52. package/dist/utils/bytesParsers/i18n/ru.json +1 -0
  53. package/dist/utils/bytesParsers/index.ts +1 -1
  54. package/dist/utils/index.js +5 -10
  55. package/dist/utils/numeral.ts +8 -0
  56. package/package.json +1 -1
  57. package/dist/components/FullNodeViewer/FullNodeViewer.js +0 -89
  58. package/dist/containers/Node/NodeOverview/NodeOverview.scss +0 -0
  59. package/dist/containers/Node/NodeOverview/NodeOverview.tsx +0 -21
  60. package/dist/containers/Storage/Storage.js +0 -350
  61. package/dist/containers/Tenant/Preview/Preview.js +0 -168
  62. package/dist/containers/Tenants/Tenants.js +0 -363
  63. package/dist/store/reducers/storage/storage.js +0 -404
  64. package/dist/utils/bytesParsers/formatBytesCustom.ts +0 -57
@@ -1,363 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
- import {connect} from 'react-redux';
5
- import _ from 'lodash';
6
- import {escapeRegExp} from 'lodash/fp';
7
-
8
- import DataTable from '@gravity-ui/react-data-table';
9
- import {Loader, TextInput, Button} from '@gravity-ui/uikit';
10
-
11
- import EntityStatus from '../../components/EntityStatus/EntityStatus';
12
- import {PoolsGraph} from '../../components/PoolsGraph/PoolsGraph';
13
- import {TabletsStatistic} from '../../components/TabletsStatistic';
14
- import {ProblemFilter} from '../../components/ProblemFilter';
15
- import {Illustration} from '../../components/Illustration';
16
- import {AutoFetcher} from '../../utils/autofetcher';
17
-
18
- import routes, {createHref} from '../../routes';
19
- import {formatCPU, formatBytesToGigabyte, formatNumber} from '../../utils';
20
- import {withSearch} from '../../HOCS';
21
- import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
22
- import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
23
- import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
24
-
25
- import {clusterName} from '../../store';
26
- import {TenantTabsGroups, TENANT_INFO_TABS} from '../Tenant/TenantPages';
27
-
28
- import './Tenants.scss';
29
-
30
- const b = cn('tenants');
31
-
32
- class Tenants extends React.Component {
33
- static renderLoader() {
34
- return (
35
- <div className={'loader'}>
36
- <Loader size="l" />
37
- </div>
38
- );
39
- }
40
-
41
- static propTypes = {
42
- loading: PropTypes.bool,
43
- wasLoaded: PropTypes.bool,
44
- error: PropTypes.bool,
45
- getTenantsInfo: PropTypes.func,
46
- tenants: PropTypes.array,
47
- searchQuery: PropTypes.string,
48
- handleSearchQuery: PropTypes.func,
49
- filter: PropTypes.string,
50
- changeFilter: PropTypes.func,
51
- cluster: PropTypes.object,
52
- singleClusterMode: PropTypes.bool,
53
- additionalTenantsInfo: PropTypes.object,
54
- };
55
-
56
- static defaultProps = {
57
- className: '',
58
- };
59
-
60
- static filterTenants(tenants, filter) {
61
- if (filter === ProblemFilterValues.ALL) {
62
- return tenants;
63
- }
64
-
65
- return _.filter(tenants, (tenant) => {
66
- return tenant.Overall && tenant.Overall !== 'Green';
67
- });
68
- }
69
-
70
- componentDidMount() {
71
- this.autofetcher = new AutoFetcher();
72
- this.props.getTenantsInfo(clusterName);
73
- this.autofetcher.fetch(() => this.props.getTenantsInfo(clusterName));
74
- }
75
-
76
- componentWillUnmount() {
77
- this.autofetcher.stop();
78
- }
79
-
80
- renderControls() {
81
- const {searchQuery, handleSearchQuery, filter, changeFilter} = this.props;
82
-
83
- return (
84
- <div className={b('controls')}>
85
- <div className={b('search')}>
86
- <TextInput
87
- placeholder="Database name"
88
- value={searchQuery}
89
- onUpdate={handleSearchQuery}
90
- hasClear
91
- autoFocus
92
- />
93
- </div>
94
- <ProblemFilter value={filter} onChange={changeFilter} />
95
- </div>
96
- );
97
- }
98
-
99
- getControlPlaneValue = (item) => {
100
- const parts = _.get(item, 'Name', []).split('/');
101
- const defaultValue = parts.length ? parts[parts.length - 1] : '—';
102
-
103
- return _.get(item, 'ControlPlane.name', defaultValue);
104
- };
105
-
106
- renderTable = () => {
107
- const {
108
- tenants = [],
109
- searchQuery,
110
- filter,
111
- handleSearchQuery,
112
- additionalTenantsInfo = {},
113
- } = this.props;
114
-
115
- const filteredTenantsBySearch = tenants.filter((item) => {
116
- const re = new RegExp(escapeRegExp(searchQuery), 'i');
117
- return re.test(item.Name) || re.test(this.getControlPlaneValue(item));
118
- });
119
- const filteredTenants = Tenants.filterTenants(filteredTenantsBySearch, filter);
120
-
121
- const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
122
-
123
- const getTenantBackend = (tenant) => {
124
- const backend = tenant.MonitoringEndpoint ?? tenant.backend;
125
- return additionalTenantsInfo.tenantBackend
126
- ? additionalTenantsInfo.tenantBackend(backend)
127
- : undefined;
128
- };
129
-
130
- const columns = [
131
- {
132
- name: 'Name',
133
- header: 'Database',
134
- render: ({value, row}) => {
135
- const backend = getTenantBackend(row);
136
- const isExternalLink = Boolean(backend);
137
- return (
138
- <div className={b('name-wrapper')}>
139
- <EntityStatus
140
- externalLink={isExternalLink}
141
- className={b('name')}
142
- name={value || 'unknown database'}
143
- withLeftTrim={true}
144
- status={row.Overall}
145
- hasClipboardButton
146
- path={createHref(routes.tenant, undefined, {
147
- name: value,
148
- backend,
149
- [TenantTabsGroups.info]: initialTenantInfoTab,
150
- })}
151
- />
152
- {additionalTenantsInfo.name && additionalTenantsInfo.name(value, row)}
153
- </div>
154
- );
155
- },
156
- width: 440,
157
- sortable: true,
158
- defaultOrder: DataTable.DESCENDING,
159
- },
160
- {
161
- name: 'ControlPlaneName',
162
- header: 'Name',
163
- render: ({row}) => {
164
- return this.getControlPlaneValue(row);
165
- },
166
- width: 200,
167
- sortable: true,
168
- defaultOrder: DataTable.DESCENDING,
169
- },
170
- {
171
- name: 'Type',
172
- width: 200,
173
- render: ({value, row}) => {
174
- if (value !== 'Serverless') {
175
- return value;
176
- }
177
-
178
- const sharedTenantName = _.find(tenants, {Id: row.ResourceId}).Name;
179
-
180
- return (
181
- <div className={b('type')}>
182
- <span className={b('type-value')}>{value}</span>
183
- <Button
184
- className={b('type-button')}
185
- onClick={() => handleSearchQuery(sharedTenantName)}
186
- >
187
- Show shared
188
- </Button>
189
- </div>
190
- );
191
- },
192
- },
193
- {
194
- name: 'State',
195
- width: 90,
196
- render: ({value}) => (value ? value.toLowerCase() : '—'),
197
- customStyle: () => ({textTransform: 'capitalize'}),
198
- },
199
- {
200
- name: 'cpu',
201
- header: 'CPU',
202
- width: 80,
203
- sortAccessor: ({Metrics = {}, CoresUsed}) => {
204
- const cpuRaw =
205
- CoresUsed !== undefined ? Number(CoresUsed) * 1_000_000 : Metrics.CPU;
206
- return isNaN(Number(cpuRaw)) ? 0 : Number(cpuRaw);
207
- },
208
- accessor: ({Metrics = {}, CoresUsed}) => {
209
- if (!isNaN(Number(CoresUsed))) {
210
- return Number(CoresUsed) * 100 > 1
211
- ? formatCPU(Number(CoresUsed) * 1_000_000)
212
- : '—';
213
- } else {
214
- return Number(Metrics.CPU) ? formatCPU(Number(Metrics.CPU)) : '—';
215
- }
216
- },
217
- align: DataTable.RIGHT,
218
- defaultOrder: DataTable.DESCENDING,
219
- },
220
- {
221
- name: 'memory',
222
- header: 'Memory',
223
- width: 120,
224
- accessor: ({Metrics = {}, MemoryUsed}) => {
225
- return !isNaN(Number(MemoryUsed)) ? Number(MemoryUsed) : Number(Metrics.Memory);
226
- },
227
- sortAccessor: ({Metrics = {}, MemoryUsed}) => {
228
- const memory = MemoryUsed ?? Metrics.Memory;
229
- return isNaN(Number(memory)) ? 0 : Number(memory);
230
- },
231
- render: ({value}) => (value ? formatBytesToGigabyte(value) : '—'),
232
- align: DataTable.RIGHT,
233
- defaultOrder: DataTable.DESCENDING,
234
- },
235
- {
236
- name: 'storage',
237
- header: 'Storage',
238
- width: 120,
239
- accessor: ({Metrics = {}, StorageAllocatedSize}) => {
240
- return !isNaN(Number(StorageAllocatedSize))
241
- ? Number(StorageAllocatedSize)
242
- : Number(Metrics.Storage);
243
- },
244
- sortAccessor: ({Metrics = {}, StorageAllocatedSize}) => {
245
- const storage = StorageAllocatedSize ?? Metrics.Storage;
246
- return isNaN(Number(storage)) ? 0 : Number(storage);
247
- },
248
- render: ({value}) => (value ? formatBytesToGigabyte(value) : '—'),
249
- align: DataTable.RIGHT,
250
- defaultOrder: DataTable.DESCENDING,
251
- },
252
- {
253
- name: 'NodeIds',
254
- header: 'Nodes',
255
- width: 100,
256
- accessor: ({NodeIds}) => NodeIds?.length || 0,
257
- sortAccessor: ({NodeIds}) => NodeIds?.length || 0,
258
- render: ({value}) => formatNumber(value),
259
- align: DataTable.RIGHT,
260
- defaultOrder: DataTable.DESCENDING,
261
- },
262
- {
263
- name: 'StorageGroups',
264
- header: 'Groups',
265
- width: 100,
266
- sortAccessor: ({StorageGroups}) =>
267
- isNaN(Number(StorageGroups)) ? 0 : Number(StorageGroups),
268
- render: ({value}) => formatNumber(value) || '—',
269
- align: DataTable.RIGHT,
270
- defaultOrder: DataTable.DESCENDING,
271
- },
272
- {
273
- name: 'PoolStats',
274
- header: 'Pools',
275
- width: 100,
276
- sortAccessor: ({PoolStats = []}) =>
277
- PoolStats.reduce((acc, item) => acc + item.Usage, 0),
278
- defaultOrder: DataTable.DESCENDING,
279
- align: DataTable.LEFT,
280
- render: ({value}) => <PoolsGraph rowInfo={value} pools={value} />,
281
- },
282
- {
283
- name: 'Tablets',
284
- header: 'Tablets States',
285
- sortable: false,
286
- width: 430,
287
- render: ({value, row}) => {
288
- const backend = getTenantBackend(row);
289
-
290
- return value ? (
291
- <TabletsStatistic
292
- path={row.Name}
293
- tablets={value}
294
- nodeIds={row.NodeIds}
295
- backend={backend}
296
- />
297
- ) : (
298
- '—'
299
- );
300
- },
301
- },
302
- ];
303
-
304
- if (filteredTenants.length === 0 && filter !== ProblemFilterValues.ALL) {
305
- return <Illustration name="thumbsUp" width="200" />;
306
- }
307
-
308
- return (
309
- <div className={b('table-wrapper')}>
310
- <DataTable
311
- theme="yandex-cloud"
312
- data={filteredTenants}
313
- columns={columns}
314
- settings={DEFAULT_TABLE_SETTINGS}
315
- dynamicRender={true}
316
- emptyDataMessage="No such tenants"
317
- />
318
- </div>
319
- );
320
- };
321
-
322
- renderContent = () => {
323
- return (
324
- <div className={b()}>
325
- {this.renderControls()}
326
- {this.renderTable()}
327
- </div>
328
- );
329
- };
330
-
331
- render() {
332
- const {loading, wasLoaded, error} = this.props;
333
-
334
- if (loading && !wasLoaded) {
335
- return Tenants.renderLoader();
336
- } else if (error) {
337
- return <div>{error.statusText}</div>;
338
- } else {
339
- return this.renderContent();
340
- }
341
- }
342
- }
343
-
344
- const mapStateToProps = (state) => {
345
- const {tenants, wasLoaded, loading, error} = state.tenants;
346
- const {singleClusterMode} = state;
347
-
348
- return {
349
- singleClusterMode,
350
- tenants,
351
- wasLoaded,
352
- loading,
353
- error,
354
- filter: state.settings.problemFilter,
355
- };
356
- };
357
-
358
- const mapDispatchToProps = {
359
- getTenantsInfo,
360
- changeFilter,
361
- };
362
-
363
- export default withSearch(connect(mapStateToProps, mapDispatchToProps)(Tenants));