ydb-embedded-ui 3.3.2 → 3.3.3

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/components/Errors/ResponseError/ResponseError.tsx +17 -0
  3. package/dist/components/Errors/ResponseError/index.ts +1 -0
  4. package/dist/components/Errors/i18n/en.json +2 -1
  5. package/dist/components/Errors/i18n/ru.json +2 -1
  6. package/dist/components/FullGroupViewer/FullGroupViewer.js +1 -1
  7. package/dist/components/InfoViewer/InfoViewer.scss +1 -1
  8. package/dist/components/InfoViewer/InfoViewer.tsx +29 -21
  9. package/dist/components/InfoViewer/formatters/index.ts +1 -0
  10. package/dist/components/InfoViewer/formatters/table.ts +40 -0
  11. package/dist/components/QueryExecutionStatus/QueryExecutionStatus.tsx +26 -8
  12. package/dist/components/QueryExecutionStatus/index.ts +1 -0
  13. package/dist/components/QueryResultTable/QueryResultTable.tsx +2 -2
  14. package/dist/containers/App/Content.js +12 -5
  15. package/dist/containers/AsideNavigation/AsideNavigation.tsx +10 -13
  16. package/dist/containers/Authentication/Authentication.scss +6 -0
  17. package/dist/containers/Authentication/Authentication.tsx +34 -15
  18. package/dist/containers/Node/NodeStructure/Pdisk.tsx +7 -10
  19. package/dist/containers/Nodes/Nodes.tsx +1 -1
  20. package/dist/containers/Nodes/getNodesColumns.tsx +4 -4
  21. package/dist/containers/Storage/PDisk/PDisk.tsx +25 -17
  22. package/dist/containers/Storage/PDisk/__tests__/colors.tsx +64 -1
  23. package/dist/containers/Storage/Storage.js +1 -1
  24. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +4 -3
  25. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +1 -1
  26. package/dist/containers/Storage/utils/index.ts +26 -10
  27. package/dist/containers/Tablet/Tablet.js +1 -1
  28. package/dist/containers/Tenant/Acl/Acl.js +1 -1
  29. package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +2 -2
  30. package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +1 -1
  31. package/dist/containers/Tenant/Diagnostics/OverloadedShards/OverloadedShards.tsx +6 -1
  32. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +10 -21
  33. package/dist/containers/Tenant/{Schema/SchemaInfoViewer/SchemaInfoViewer.scss → Diagnostics/Overview/TableInfo/TableInfo.scss} +8 -10
  34. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +71 -0
  35. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +5 -0
  36. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/index.ts +11 -0
  37. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/ru.json +5 -0
  38. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/index.ts +1 -0
  39. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +96 -0
  40. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +7 -1
  41. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +3 -1
  42. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +16 -11
  43. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +37 -23
  44. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.scss +4 -0
  45. package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +1 -1
  46. package/dist/containers/Tenants/Tenants.js +4 -3
  47. package/dist/routes.ts +1 -0
  48. package/dist/services/api.js +4 -1
  49. package/dist/store/reducers/shardsWorkload.ts +2 -1
  50. package/dist/store/reducers/storage.js +1 -1
  51. package/dist/utils/constants.ts +1 -1
  52. package/dist/utils/index.js +3 -1
  53. package/dist/utils/prepareQueryExplain.ts +1 -1
  54. package/package.json +5 -3
  55. package/dist/containers/Tenant/Diagnostics/Overview/Overview.scss +0 -13
  56. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +0 -201
@@ -7,7 +7,7 @@ import {TPDiskState} from '../../../../types/api/pdisk';
7
7
  import {PDisk} from '../PDisk';
8
8
 
9
9
  describe('PDisk state', () => {
10
- it('Should determine severity based on State', () => {
10
+ it('Should determine severity based on State if space severity is OK', () => {
11
11
  const {getAllByRole} = renderWithStore(
12
12
  <MemoryRouter>
13
13
  <PDisk nodeId={1} data={{State: TPDiskState.Normal}} />
@@ -20,6 +20,55 @@ describe('PDisk state', () => {
20
20
  expect(normalDisk.className).not.toBe(erroredDisk.className);
21
21
  });
22
22
 
23
+ it('Should determine severity based on space utilization if state severity is OK', () => {
24
+ const {getAllByRole} = renderWithStore(
25
+ <MemoryRouter>
26
+ <PDisk
27
+ nodeId={1}
28
+ data={{State: TPDiskState.Normal, AvailableSize: '100', TotalSize: '100'}}
29
+ />
30
+ <PDisk
31
+ nodeId={2}
32
+ data={{State: TPDiskState.Normal, AvailableSize: '14', TotalSize: '100'}}
33
+ />
34
+ <PDisk
35
+ nodeId={3}
36
+ data={{State: TPDiskState.Normal, AvailableSize: '4', TotalSize: '100'}}
37
+ />
38
+ </MemoryRouter>,
39
+ );
40
+
41
+ const [disk1, disk2, disk3] = getAllByRole('meter');
42
+
43
+ expect(disk1.className).toMatch(/_green\b/i);
44
+ expect(disk2.className).toMatch(/_yellow\b/i);
45
+ expect(disk3.className).toMatch(/_red\b/i);
46
+ });
47
+
48
+ it('Should determine severity based on max severity of state and space utilization ', () => {
49
+ const {getAllByRole} = renderWithStore(
50
+ <MemoryRouter>
51
+ <PDisk
52
+ nodeId={1}
53
+ data={{
54
+ State: TPDiskState.ChunkQuotaError,
55
+ AvailableSize: '100',
56
+ TotalSize: '100',
57
+ }}
58
+ />
59
+ <PDisk
60
+ nodeId={2}
61
+ data={{State: TPDiskState.Normal, AvailableSize: '4', TotalSize: '100'}}
62
+ />
63
+ </MemoryRouter>,
64
+ );
65
+
66
+ const [disk1, disk2] = getAllByRole('meter');
67
+
68
+ expect(disk1.className).toMatch(/_red\b/i);
69
+ expect(disk2.className).toMatch(/_red\b/i);
70
+ });
71
+
23
72
  it('Should display as unavailabe when no State is provided', () => {
24
73
  const {getAllByRole} = renderWithStore(
25
74
  <MemoryRouter>
@@ -34,4 +83,18 @@ describe('PDisk state', () => {
34
83
  expect(disk1.className).toMatch(/_grey\b/i);
35
84
  expect(disk2.className).not.toMatch(/_grey\b/i);
36
85
  });
86
+
87
+ it('Should display as unavailabe when no State is provided event if space severity is not OK', () => {
88
+ const {getAllByRole} = renderWithStore(
89
+ <MemoryRouter>
90
+ <PDisk nodeId={1} data={{AvailableSize: '14', TotalSize: '100'}} />
91
+ <PDisk nodeId={2} data={{AvailableSize: '4', TotalSize: '100'}} />
92
+ </MemoryRouter>,
93
+ );
94
+
95
+ const [disk1, disk2] = getAllByRole('meter');
96
+
97
+ expect(disk1.className).toMatch(/_grey\b/i);
98
+ expect(disk2.className).toMatch(/_grey\b/i);
99
+ });
37
100
  });
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import {connect} from 'react-redux';
4
4
  import cn from 'bem-cn-lite';
5
- import DataTable from '@yandex-cloud/react-data-table';
5
+ import DataTable from '@gravity-ui/react-data-table';
6
6
  import {RadioButton} from '@gravity-ui/uikit';
7
7
 
8
8
  import {Search} from '../../components/Search';
@@ -1,6 +1,6 @@
1
1
  import _ from 'lodash';
2
2
  import cn from 'bem-cn-lite';
3
- import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-table';
3
+ import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
4
4
  import {Icon, Label, Popover, PopoverBehavior} from '@gravity-ui/uikit';
5
5
 
6
6
  import shieldIcon from '../../../assets/icons/shield.svg';
@@ -20,7 +20,7 @@ import {getUsage, isFullDonorData} from '../../../utils/storage';
20
20
 
21
21
  import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
22
22
  import {VDisk} from '../VDisk';
23
- import {getDegradedSeverity, getUsageSeverity} from '../utils';
23
+ import {getDegradedSeverity, getUsageSeverityForStorageGroup} from '../utils';
24
24
 
25
25
  import i18n from './i18n';
26
26
  import './StorageGroups.scss';
@@ -127,6 +127,7 @@ function StorageGroups({
127
127
  {
128
128
  name: TableColumnsIds.Type,
129
129
  header: tableColumnsNames[TableColumnsIds.Type],
130
+ // prettier-ignore
130
131
  render: ({value, row}) => (
131
132
  <>
132
133
  <Label>{(value as string) || '—'}</Label>
@@ -164,7 +165,7 @@ function StorageGroups({
164
165
  // but the absence of a value is more clear
165
166
  return row.Limit ? (
166
167
  <Label
167
- theme={getUsageSeverity(usage)}
168
+ theme={getUsageSeverityForStorageGroup(usage)}
168
169
  className={b('usage-label', {overload: usage >= 90})}
169
170
  >
170
171
  {usage}%
@@ -1,7 +1,7 @@
1
1
  import _ from 'lodash';
2
2
  import cn from 'bem-cn-lite';
3
3
 
4
- import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-table';
4
+ import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
5
5
  import {Popover, PopoverBehavior} from '@gravity-ui/uikit';
6
6
 
7
7
  import {VisibleEntities} from '../../../store/reducers/storage';
@@ -1,12 +1,14 @@
1
1
  import type {IStoragePoolGroup} from '../../../types/store/storage';
2
+ import {EFlag} from '../../../types/api/enums';
2
3
 
3
4
  export * from './constants';
4
5
 
5
- const generateEvaluator = <
6
- OkLevel extends string,
7
- WarnLevel extends string,
8
- CritLevel extends string
9
- >(warn: number, crit: number, levels: [OkLevel, WarnLevel, CritLevel]) =>
6
+ const generateEvaluator =
7
+ <OkLevel extends string, WarnLevel extends string, CritLevel extends string>(
8
+ warn: number,
9
+ crit: number,
10
+ levels: [OkLevel, WarnLevel, CritLevel],
11
+ ) =>
10
12
  (value: number) => {
11
13
  if (0 <= value && value < warn) {
12
14
  return levels[0];
@@ -34,12 +36,26 @@ const canEvaluateErasureSpecies = (value?: string): value is keyof typeof degrad
34
36
  value !== undefined && value in degradationEvaluators;
35
37
 
36
38
  export const getDegradedSeverity = (group: IStoragePoolGroup) => {
37
- const evaluate = canEvaluateErasureSpecies(group.ErasureSpecies) ?
38
- degradationEvaluators[group.ErasureSpecies] :
39
- defaultDegradationEvaluator;
39
+ const evaluate = canEvaluateErasureSpecies(group.ErasureSpecies)
40
+ ? degradationEvaluators[group.ErasureSpecies]
41
+ : defaultDegradationEvaluator;
40
42
 
41
43
  return evaluate(group.Missing);
42
44
  };
43
45
 
44
- export const getUsageSeverity = generateEvaluator(80, 85, ['success', 'warning', 'danger']);
45
- export const getUsageSeverityForEntityStatus = generateEvaluator(80, 85, ['Green', 'Yellow', 'Red']);
46
+ export const getUsageSeverityForStorageGroup = generateEvaluator(80, 85, [
47
+ 'success',
48
+ 'warning',
49
+ 'danger',
50
+ ]);
51
+ export const getUsageSeverityForEntityStatus = generateEvaluator(80, 85, [
52
+ 'Green',
53
+ 'Yellow',
54
+ 'Red',
55
+ ]);
56
+
57
+ export const getUsageSeverityForPDisk = generateEvaluator(85, 95, [
58
+ EFlag.Green,
59
+ EFlag.Yellow,
60
+ EFlag.Red,
61
+ ]);
@@ -16,7 +16,7 @@ import {Tag} from '../../components/Tag/Tag';
16
16
  import Icon from '../../components/Icon/Icon';
17
17
  import EmptyState from '../../components/EmptyState/EmptyState';
18
18
  import {Link as ExternalLink, Button, Loader} from '@gravity-ui/uikit';
19
- import DataTable from '@yandex-cloud/react-data-table';
19
+ import DataTable from '@gravity-ui/react-data-table';
20
20
  import CriticalActionDialog from '../../components/CriticalActionDialog/CriticalActionDialog';
21
21
  import routes, {createHref} from '../../routes';
22
22
  import {getDefaultNodePath} from '../Node/NodePages';
@@ -4,7 +4,7 @@ import cn from 'bem-cn-lite';
4
4
  import _ from 'lodash';
5
5
  import {connect} from 'react-redux';
6
6
  import {Loader} from '@gravity-ui/uikit';
7
- import DataTable from '@yandex-cloud/react-data-table';
7
+ import DataTable from '@gravity-ui/react-data-table';
8
8
  import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
9
9
 
10
10
  import './Acl.scss';
@@ -1,9 +1,9 @@
1
1
  import {useCallback, useEffect, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import block from 'bem-cn-lite';
4
- import { escapeRegExp } from 'lodash/fp';
4
+ import {escapeRegExp} from 'lodash/fp';
5
5
 
6
- import DataTable, {Column} from '@yandex-cloud/react-data-table';
6
+ import DataTable, {Column} from '@gravity-ui/react-data-table';
7
7
 
8
8
  import type {EPathType} from '../../../../types/api/schema';
9
9
  import {Loader} from '../../../../components/Loader';
@@ -2,7 +2,7 @@ import {useEffect, useMemo} from 'react';
2
2
  import cn from 'bem-cn-lite';
3
3
  import {connect} from 'react-redux';
4
4
  import {Loader} from '@gravity-ui/uikit';
5
- import DataTable from '@yandex-cloud/react-data-table';
5
+ import DataTable from '@gravity-ui/react-data-table';
6
6
 
7
7
  import Icon from '../../../../components/Icon/Icon';
8
8
 
@@ -2,7 +2,7 @@ import {useState, useContext, useEffect, useMemo} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
 
5
- import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-table';
5
+ import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
6
6
  import {Loader} from '@gravity-ui/uikit';
7
7
 
8
8
  import {DateRange, DateRangeValues} from '../../../../components/DateRange';
@@ -53,6 +53,7 @@ const tableColumnsNames = {
53
53
  NodeId: 'NodeId',
54
54
  PeakTime: 'PeakTime',
55
55
  InFlightTxCount: 'InFlightTxCount',
56
+ IntervalEnd: 'IntervalEnd',
56
57
  };
57
58
 
58
59
  function prepareCPUWorkloadValue(value: string) {
@@ -227,6 +228,10 @@ export const OverloadedShards = ({tenantPath, type}: OverloadedShardsProps) => {
227
228
  align: DataTable.RIGHT,
228
229
  sortable: false,
229
230
  },
231
+ {
232
+ name: tableColumnsNames.IntervalEnd,
233
+ render: ({value}) => formatDateTime(new Date(value as string).getTime()),
234
+ }
230
235
  ];
231
236
  }, [dispatch, history, tenantPath]);
232
237
 
@@ -1,15 +1,15 @@
1
1
  import {ReactNode, useCallback, useMemo} from 'react';
2
2
  import {shallowEqual, useDispatch, useSelector} from 'react-redux';
3
- import cn from 'bem-cn-lite';
4
3
 
5
- import {Loader} from '@gravity-ui/uikit';
4
+ import {Loader} from '../../../../components/Loader';
6
5
 
7
6
  //@ts-ignore
8
- import SchemaInfoViewer from '../../Schema/SchemaInfoViewer/SchemaInfoViewer';
9
7
  import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo';
8
+ import {ResponseError} from '../../../../components/Errors/ResponseError';
10
9
 
11
10
  import {TopicInfo} from './TopicInfo';
12
11
  import {ChangefeedInfo} from './ChangefeedInfo';
12
+ import {TableInfo} from './TableInfo';
13
13
 
14
14
  import {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
15
15
  import {
@@ -33,8 +33,6 @@ import {
33
33
  } from '../../../../store/reducers/olapStats';
34
34
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
35
35
 
36
- import './Overview.scss';
37
-
38
36
  function prepareOlapTableGeneral(item?: TEvDescribeSchemeResult, olapStats?: any[]) {
39
37
  const tableData = item?.PathDescription?.ColumnTableDescription;
40
38
 
@@ -70,8 +68,6 @@ interface OverviewProps {
70
68
  tenantName?: string;
71
69
  }
72
70
 
73
- const b = cn('kv-tenant-overview');
74
-
75
71
  function Overview({type, tenantName, className}: OverviewProps) {
76
72
  const dispatch = useDispatch();
77
73
 
@@ -81,6 +77,7 @@ function Overview({type, tenantName, className}: OverviewProps) {
81
77
  wasLoaded,
82
78
  autorefresh,
83
79
  currentSchemaPath,
80
+ error,
84
81
  } = useSelector((state: any) => state.schema);
85
82
 
86
83
  const {data: {result: olapStats} = {result: undefined}, loading: olapStatsLoading} =
@@ -144,14 +141,6 @@ function Overview({type, tenantName, className}: OverviewProps) {
144
141
  : currentItem;
145
142
  }, [type, olapStats, currentItem]);
146
143
 
147
- const renderLoader = () => {
148
- return (
149
- <div className={b('loader')}>
150
- <Loader size="m" />
151
- </div>
152
- );
153
- };
154
-
155
144
  const renderContent = () => {
156
145
  // verbose mapping to guarantee a correct render for new path types
157
146
  // TS will error when a new type is added but not mapped here
@@ -170,15 +159,15 @@ function Overview({type, tenantName, className}: OverviewProps) {
170
159
  [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={schemaData} />,
171
160
  };
172
161
 
173
- return (
174
- (type && pathTypeToComponent[type]?.()) || (
175
- <SchemaInfoViewer fullPath={currentItem.Path} data={schemaData} />
176
- )
177
- );
162
+ return (type && pathTypeToComponent[type]?.()) || <TableInfo data={schemaData} />;
178
163
  };
179
164
 
180
165
  if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
181
- return renderLoader();
166
+ return <Loader size="m" />;
167
+ }
168
+
169
+ if (error) {
170
+ return <ResponseError error={error} />;
182
171
  }
183
172
 
184
173
  return <div className={className}>{renderContent()}</div>;
@@ -1,6 +1,12 @@
1
- .schema-info-viewer {
1
+ @import '../../../../../styles/mixins.scss';
2
+
3
+ .ydb-diagnostics-table-info {
2
4
  overflow: auto;
3
5
 
6
+ &__title {
7
+ @include info-viewer-title();
8
+ }
9
+
4
10
  &__row {
5
11
  display: flex;
6
12
  flex-wrap: wrap;
@@ -19,19 +25,11 @@
19
25
  }
20
26
  }
21
27
 
22
- &__item {
28
+ &__info-block {
23
29
  margin-bottom: 20px;
24
30
 
25
31
  .info-viewer__items {
26
32
  grid-template-columns: minmax(max-content, 280px);
27
33
  }
28
34
  }
29
-
30
- &__title {
31
- margin: 15px 0 10px;
32
-
33
- font-size: var(--yc-text-body-2-font-size);
34
- font-weight: 600;
35
- line-height: var(--yc-text-body-2-line-height);
36
- }
37
35
  }
@@ -0,0 +1,71 @@
1
+ import {useMemo} from 'react';
2
+ import cn from 'bem-cn-lite';
3
+
4
+ import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
5
+
6
+ import {InfoViewer} from '../../../../../components/InfoViewer';
7
+
8
+ import {getEntityName} from '../../../utils';
9
+
10
+ import {prepareTableInfo} from './prepareTableInfo';
11
+
12
+ import i18n from './i18n';
13
+
14
+ import './TableInfo.scss';
15
+
16
+ const b = cn('ydb-diagnostics-table-info');
17
+
18
+ interface TableInfoProps {
19
+ data?: TEvDescribeSchemeResult;
20
+ }
21
+
22
+ export const TableInfo = ({data}: TableInfoProps) => {
23
+ const entityName = getEntityName(data?.PathDescription);
24
+
25
+ const {
26
+ generalTableInfo = [],
27
+ tableStatsInfo = [],
28
+ tabletMetricsInfo = [],
29
+ partitionConfigInfo = [],
30
+ } = useMemo(() => prepareTableInfo(data), [data]);
31
+
32
+ return (
33
+ <div className={b()}>
34
+ <InfoViewer
35
+ info={generalTableInfo}
36
+ title={entityName}
37
+ className={b('info-block')}
38
+ renderEmptyState={() => <div className={b('title')}>{entityName}</div>}
39
+ />
40
+ <div className={b('row')}>
41
+ {tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
42
+ <div className={b('col')}>
43
+ <InfoViewer
44
+ info={tabletMetricsInfo}
45
+ title={i18n('tabletMetrics')}
46
+ className={b('info-block')}
47
+ renderEmptyState={() => null}
48
+ />
49
+ <InfoViewer
50
+ info={partitionConfigInfo}
51
+ title={i18n('partitionConfig')}
52
+ className={b('info-block')}
53
+ renderEmptyState={() => null}
54
+ />
55
+ </div>
56
+ ) : null}
57
+ <div className={b('col')}>
58
+ {tableStatsInfo.map((info, index) => (
59
+ <InfoViewer
60
+ key={index}
61
+ info={info}
62
+ title={index === 0 ? i18n('tableStats') : undefined}
63
+ className={b('info-block')}
64
+ renderEmptyState={() => null}
65
+ />
66
+ ))}
67
+ </div>
68
+ </div>
69
+ </div>
70
+ );
71
+ };
@@ -0,0 +1,5 @@
1
+ {
2
+ "tableStats": "Table Stats",
3
+ "tabletMetrics": "Tablet Metrics",
4
+ "partitionConfig": "Partition Config"
5
+ }
@@ -0,0 +1,11 @@
1
+ import {i18n, Lang} from '../../../../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+ import ru from './ru.json';
5
+
6
+ const COMPONENT = 'ydb-diagnostics-overview-table-info';
7
+
8
+ i18n.registerKeyset(Lang.En, COMPONENT, en);
9
+ i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
10
+
11
+ export default i18n.keyset(COMPONENT);
@@ -0,0 +1,5 @@
1
+ {
2
+ "tableStats": "Статистика таблицы",
3
+ "tabletMetrics": "Метрики таблетки",
4
+ "partitionConfig": "Конфигурация партиции"
5
+ }
@@ -0,0 +1 @@
1
+ export * from './TableInfo';
@@ -0,0 +1,96 @@
1
+ import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
2
+
3
+ import {formatObject} from '../../../../../components/InfoViewer';
4
+ import {
5
+ formatFollowerGroupItem,
6
+ formatPartitionConfigItem,
7
+ formatTableStatsItem,
8
+ formatTabletMetricsItem,
9
+ } from '../../../../../components/InfoViewer/formatters';
10
+
11
+ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
12
+ if (!data) {
13
+ return {};
14
+ }
15
+
16
+ const {PathDescription = {}} = data;
17
+
18
+ const {
19
+ TableStats = {},
20
+ TabletMetrics = {},
21
+ Table: {PartitionConfig = {}} = {},
22
+ } = PathDescription;
23
+
24
+ const {
25
+ PartCount,
26
+ RowCount,
27
+ DataSize,
28
+ IndexSize,
29
+
30
+ LastAccessTime,
31
+ LastUpdateTime,
32
+
33
+ ImmediateTxCompleted,
34
+ PlannedTxCompleted,
35
+ TxRejectedByOverload,
36
+ TxRejectedBySpace,
37
+ TxCompleteLagMsec,
38
+ InFlightTxCount,
39
+
40
+ RowUpdates,
41
+ RowDeletes,
42
+ RowReads,
43
+ RangeReads,
44
+ RangeReadRows,
45
+
46
+ ...restTableStats
47
+ } = TableStats;
48
+
49
+ const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig;
50
+
51
+ const generalTableInfo = formatObject(formatTableStatsItem, {
52
+ PartCount,
53
+ RowCount,
54
+ DataSize,
55
+ IndexSize,
56
+ ...restTableStats,
57
+ });
58
+
59
+ const tableStatsInfo = [
60
+ formatObject(formatTableStatsItem, {
61
+ LastAccessTime,
62
+ LastUpdateTime,
63
+ }),
64
+ formatObject(formatTableStatsItem, {
65
+ ImmediateTxCompleted,
66
+ PlannedTxCompleted,
67
+ TxRejectedByOverload,
68
+ TxRejectedBySpace,
69
+ TxCompleteLagMsec,
70
+ InFlightTxCount,
71
+ }),
72
+ formatObject(formatTableStatsItem, {
73
+ RowUpdates,
74
+ RowDeletes,
75
+ RowReads,
76
+ RangeReads,
77
+ RangeReadRows,
78
+ }),
79
+ ];
80
+
81
+ const tabletMetricsInfo = formatObject(formatTabletMetricsItem, TabletMetrics);
82
+
83
+ let partitionConfigInfo = [];
84
+
85
+ if (Array.isArray(FollowerGroups) && FollowerGroups.length > 0) {
86
+ partitionConfigInfo = formatObject(formatFollowerGroupItem, FollowerGroups[0]);
87
+ } else if (FollowerCount !== undefined) {
88
+ partitionConfigInfo.push(formatPartitionConfigItem('FollowerCount', FollowerCount));
89
+ } else if (CrossDataCenterFollowerCount !== undefined) {
90
+ partitionConfigInfo.push(
91
+ formatPartitionConfigItem('CrossDataCenterFollowerCount', CrossDataCenterFollowerCount),
92
+ );
93
+ }
94
+
95
+ return {generalTableInfo, tableStatsInfo, tabletMetricsInfo, partitionConfigInfo};
96
+ };
@@ -2,7 +2,7 @@ import {useCallback, useEffect, useRef, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
 
5
- import DataTable, {Column, Settings} from '@yandex-cloud/react-data-table';
5
+ import DataTable, {Column, Settings} from '@gravity-ui/react-data-table';
6
6
  import {Loader} from '@gravity-ui/uikit';
7
7
 
8
8
  import {DateRange, DateRangeValues} from '../../../../components/DateRange';
@@ -21,6 +21,7 @@ import type {EPathType} from '../../../../types/api/schema';
21
21
  import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
22
22
  import type {IQueryResult} from '../../../../types/store/query';
23
23
 
24
+ import {formatDateTime} from '../../../../utils';
24
25
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
25
26
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
26
27
  import {prepareQueryError} from '../../../../utils/query';
@@ -51,6 +52,11 @@ const COLUMNS: Column<KeyValueRow>[] = [
51
52
  sortable: false,
52
53
  render: ({value}) => <TruncatedQuery value={value} maxQueryHeight={MAX_QUERY_HEIGHT} />,
53
54
  },
55
+ {
56
+ name: 'IntervalEnd',
57
+ width: 140,
58
+ render: ({value}) => formatDateTime(new Date(value as string).getTime()),
59
+ },
54
60
  ];
55
61
 
56
62
  interface TopQueriesProps {
@@ -26,6 +26,8 @@ import {
26
26
  TColumnTableDescription,
27
27
  TDirEntry,
28
28
  } from '../../../types/api/schema';
29
+
30
+ import {formatDateTime} from '../../../utils';
29
31
  import {isColumnEntityType, isIndexTable, isTableType} from '../utils/schema';
30
32
 
31
33
  import {
@@ -201,7 +203,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
201
203
  const startTimeInMilliseconds = Number(currentSchemaData?.CreateStep);
202
204
  let createTime = '';
203
205
  if (startTimeInMilliseconds) {
204
- createTime = new Date(startTimeInMilliseconds).toUTCString();
206
+ createTime = formatDateTime(startTimeInMilliseconds);
205
207
  }
206
208
 
207
209
  component = <InfoViewer info={[{label: 'Create time', value: createTime}]} />;