ydb-embedded-ui 3.4.5 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/components/InfoViewer/formatters/table.ts +6 -0
  3. package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
  4. package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
  5. package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
  6. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
  7. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
  8. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
  9. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
  10. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
  11. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
  12. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
  13. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +1 -0
  14. package/dist/routes.ts +1 -1
  15. package/dist/services/api.js +3 -3
  16. package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +51 -21
  17. package/dist/store/reducers/executeTopQueries.ts +5 -1
  18. package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
  19. package/dist/store/reducers/settings.js +1 -1
  20. package/dist/store/reducers/storage.js +5 -7
  21. package/dist/types/api/query.ts +4 -1
  22. package/dist/types/api/schema.ts +523 -3
  23. package/dist/types/common.ts +1 -0
  24. package/dist/types/store/executeQuery.ts +42 -0
  25. package/dist/types/store/olapStats.ts +14 -0
  26. package/dist/utils/query.test.ts +42 -29
  27. package/dist/utils/query.ts +34 -22
  28. package/dist/utils/timeParsers/formatDuration.ts +30 -12
  29. package/dist/utils/timeParsers/i18n/en.json +4 -0
  30. package/dist/utils/timeParsers/i18n/ru.json +4 -0
  31. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.5.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.5...v3.5.0) (2023-04-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * **TableInfo:** extend Table and ColumnTable info ([89e54aa](https://github.com/ydb-platform/ydb-embedded-ui/commit/89e54aa97d7bcbabfd5100daeb1dc0c03608e86e))
9
+ * **TopQueries:** add columns ([b49b98d](https://github.com/ydb-platform/ydb-embedded-ui/commit/b49b98db2da08c355b23f4a33bf05247530543db))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **settings:** use system theme by default ([726c9cb](https://github.com/ydb-platform/ydb-embedded-ui/commit/726c9cb14d7f87cc9248340d1ebebfc8bf0d0384))
15
+ * **Storage:** fix incorrect usage on zero available space ([2704cd7](https://github.com/ydb-platform/ydb-embedded-ui/commit/2704cd7c696d337cc8e3af68941cf444f8dfae81))
16
+ * **TableInfo:** add default format for FollowerGroup fields ([961334a](https://github.com/ydb-platform/ydb-embedded-ui/commit/961334aabe89672994f0f3440e20602e180b3394))
17
+ * **Tablet:** fix dialog type enum ([c477042](https://github.com/ydb-platform/ydb-embedded-ui/commit/c477042cacc2e777cae4bd6981381a8042c603ed))
18
+ * **TopQueries:** enable go back to TopQueries from Query tab ([bbdfe72](https://github.com/ydb-platform/ydb-embedded-ui/commit/bbdfe726c9081f01422dca787b83399ea44b3956))
19
+ * **TopShards:** fix table crash on undefined values ([604e99a](https://github.com/ydb-platform/ydb-embedded-ui/commit/604e99a9427021c61ceb8ea366e316e629032b84))
20
+ * **TruncatedQuery:** wrap message ([f41b7ff](https://github.com/ydb-platform/ydb-embedded-ui/commit/f41b7ff33ac0145446ca89aab031036247f3ddf8))
21
+
3
22
  ## [3.4.5](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.4...v3.4.5) (2023-03-30)
4
23
 
5
24
 
@@ -20,6 +20,12 @@ export const formatFollowerGroupItem = createInfoFormatter<TFollowerGroup>({
20
20
  values: {
21
21
  FollowerCount: formatNumber,
22
22
  },
23
+ labels: {
24
+ // Make it shorter to fit label width
25
+ FollowerCountPerDataCenter: 'FollowerCountPerDC',
26
+ },
27
+ // Most of the FollowerGroup fields are arrays or boolean
28
+ defaultValueFormatter: (value) => value && String(value),
23
29
  });
24
30
 
25
31
  export const formatPartitionConfigItem = createInfoFormatter<TPartitionConfig>({
@@ -16,7 +16,7 @@ function TruncatedQuery({value, maxQueryHeight}) {
16
16
  return (
17
17
  <React.Fragment>
18
18
  <span className={b()}>{content}</span>
19
- <span className={b({color: 'secondary'})}>{message}</span>
19
+ <span className={b('message', {color: 'secondary'})}>{message}</span>
20
20
  </React.Fragment>
21
21
  );
22
22
  }
@@ -5,9 +5,13 @@
5
5
  white-space: pre;
6
6
  word-break: break-word;
7
7
 
8
- &_color {
9
- &_secondary {
10
- color: var(--yc-color-text-secondary);
8
+ &__message {
9
+ white-space: pre-wrap;
10
+
11
+ &_color {
12
+ &_secondary {
13
+ color: var(--yc-color-text-secondary);
14
+ }
11
15
  }
12
16
  }
13
17
  }
@@ -21,7 +21,7 @@ export const NODE_PAGES = [
21
21
  },
22
22
  ];
23
23
 
24
- export function getDefaultNodePath(nodeId) {
24
+ export function getDefaultNodePath(nodeId: string | number) {
25
25
  return createHref(routes.node, {
26
26
  id: nodeId,
27
27
  activeTab: OVERVIEW,
@@ -9,8 +9,8 @@ import {b} from '../Tablet';
9
9
 
10
10
  enum EVisibleDialogType {
11
11
  'kill' = 'kill',
12
- 'stop' = 'kill',
13
- 'resume' = 'kill',
12
+ 'stop' = 'stop',
13
+ 'resume' = 'resume',
14
14
  }
15
15
 
16
16
  type VisibleDialogType = EVisibleDialogType | null;
@@ -1,4 +1,4 @@
1
- import {ReactNode, useCallback, useMemo} from 'react';
1
+ import {ReactNode, useCallback} from 'react';
2
2
  import {shallowEqual, useDispatch, useSelector} from 'react-redux';
3
3
 
4
4
  import {Loader} from '../../../../components/Loader';
@@ -11,7 +11,7 @@ import {TopicInfo} from './TopicInfo';
11
11
  import {ChangefeedInfo} from './ChangefeedInfo';
12
12
  import {TableInfo} from './TableInfo';
13
13
 
14
- import {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
14
+ import {EPathType} from '../../../../types/api/schema';
15
15
  import {
16
16
  isEntityWithMergedImplementation,
17
17
  isColumnEntityType,
@@ -33,35 +33,6 @@ import {
33
33
  } from '../../../../store/reducers/olapStats';
34
34
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
35
35
 
36
- function prepareOlapTableGeneral(item?: TEvDescribeSchemeResult, olapStats?: any[]) {
37
- const tableData = item?.PathDescription?.ColumnTableDescription;
38
-
39
- const Bytes = olapStats?.reduce((acc, el) => {
40
- acc += parseInt(el.Bytes) || 0;
41
- return acc;
42
- }, 0);
43
- const Rows = olapStats?.reduce((acc, el) => {
44
- acc += parseInt(el.Rows) || 0;
45
- return acc;
46
- }, 0);
47
- const tabletIds = olapStats?.reduce((acc, el) => {
48
- acc.add(el.TabletId);
49
- return acc;
50
- }, new Set());
51
-
52
- return {
53
- PathDescription: {
54
- Self: item?.PathDescription?.Self,
55
- TableStats: {
56
- ColumnShardCount: tableData?.ColumnShardCount,
57
- Bytes: Bytes?.toLocaleString('ru-RU', {useGrouping: true}) ?? 0,
58
- Rows: Rows?.toLocaleString('ru-RU', {useGrouping: true}) ?? 0,
59
- Parts: tabletIds?.size ?? 0,
60
- },
61
- },
62
- };
63
- }
64
-
65
36
  interface OverviewProps {
66
37
  type?: EPathType;
67
38
  className?: string;
@@ -81,7 +52,7 @@ function Overview({type, tenantName, className}: OverviewProps) {
81
52
  } = useSelector((state: any) => state.schema);
82
53
 
83
54
  const {data: {result: olapStats} = {result: undefined}, loading: olapStatsLoading} =
84
- useSelector((state: any) => state.olapStats);
55
+ useTypedSelector((state) => state.olapStats);
85
56
 
86
57
  const loading = schemaLoading || olapStatsLoading;
87
58
 
@@ -134,13 +105,6 @@ function Overview({type, tenantName, className}: OverviewProps) {
134
105
 
135
106
  useAutofetcher(fetchData, [fetchData], autorefresh);
136
107
 
137
- const schemaData = useMemo(() => {
138
- return isTableType(type) && isColumnEntityType(type)
139
- ? // process data for ColumnTable
140
- prepareOlapTableGeneral(currentItem, olapStats)
141
- : currentItem;
142
- }, [type, olapStats, currentItem]);
143
-
144
108
  const renderContent = () => {
145
109
  // verbose mapping to guarantee a correct render for new path types
146
110
  // TS will error when a new type is added but not mapped here
@@ -149,17 +113,21 @@ function Overview({type, tenantName, className}: OverviewProps) {
149
113
  [EPathType.EPathTypeDir]: undefined,
150
114
  [EPathType.EPathTypeTable]: undefined,
151
115
  [EPathType.EPathTypeSubDomain]: undefined,
152
- [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={schemaData} />,
116
+ [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={currentItem} />,
153
117
  [EPathType.EPathTypeExtSubDomain]: undefined,
154
118
  [EPathType.EPathTypeColumnStore]: undefined,
155
119
  [EPathType.EPathTypeColumnTable]: undefined,
156
120
  [EPathType.EPathTypeCdcStream]: () => (
157
- <ChangefeedInfo data={schemaData} childrenPaths={mergedChildrenPaths} />
121
+ <ChangefeedInfo data={currentItem} childrenPaths={mergedChildrenPaths} />
158
122
  ),
159
- [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={schemaData} />,
123
+ [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={currentItem} />,
160
124
  };
161
125
 
162
- return (type && pathTypeToComponent[type]?.()) || <TableInfo data={schemaData} />;
126
+ return (
127
+ (type && pathTypeToComponent[type]?.()) || (
128
+ <TableInfo data={currentItem} type={type} olapStats={olapStats} />
129
+ )
130
+ );
163
131
  };
164
132
 
165
133
  if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
@@ -1,8 +1,8 @@
1
1
  import {useMemo} from 'react';
2
2
  import cn from 'bem-cn-lite';
3
3
 
4
- import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
5
-
4
+ import type {EPathType, TEvDescribeSchemeResult} from '../../../../../types/api/schema';
5
+ import type {KeyValueRow} from '../../../../../types/api/query';
6
6
  import {InfoViewer} from '../../../../../components/InfoViewer';
7
7
 
8
8
  import {getEntityName} from '../../../utils';
@@ -17,27 +17,40 @@ const b = cn('ydb-diagnostics-table-info');
17
17
 
18
18
  interface TableInfoProps {
19
19
  data?: TEvDescribeSchemeResult;
20
+ type?: EPathType;
21
+ olapStats?: KeyValueRow[];
20
22
  }
21
23
 
22
- export const TableInfo = ({data}: TableInfoProps) => {
24
+ export const TableInfo = ({data, type, olapStats}: TableInfoProps) => {
23
25
  const entityName = getEntityName(data?.PathDescription);
24
26
 
25
27
  const {
26
- generalTableInfo = [],
28
+ generalInfo = [],
27
29
  tableStatsInfo = [],
28
30
  tabletMetricsInfo = [],
29
31
  partitionConfigInfo = [],
30
- } = useMemo(() => prepareTableInfo(data), [data]);
32
+ } = useMemo(() => prepareTableInfo(data, type, olapStats), [data, type, olapStats]);
31
33
 
32
34
  return (
33
35
  <div className={b()}>
34
36
  <InfoViewer
35
- info={generalTableInfo}
37
+ info={generalInfo}
36
38
  title={entityName}
37
39
  className={b('info-block')}
38
40
  renderEmptyState={() => <div className={b('title')}>{entityName}</div>}
39
41
  />
40
42
  <div className={b('row')}>
43
+ <div className={b('col')}>
44
+ {tableStatsInfo.map((info, index) => (
45
+ <InfoViewer
46
+ key={index}
47
+ info={info}
48
+ title={index === 0 ? i18n('tableStats') : undefined}
49
+ className={b('info-block')}
50
+ renderEmptyState={() => null}
51
+ />
52
+ ))}
53
+ </div>
41
54
  {tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
42
55
  <div className={b('col')}>
43
56
  <InfoViewer
@@ -54,17 +67,6 @@ export const TableInfo = ({data}: TableInfoProps) => {
54
67
  />
55
68
  </div>
56
69
  ) : 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
70
  </div>
69
71
  </div>
70
72
  );
@@ -1,6 +1,16 @@
1
- import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
2
-
3
- import {formatObject} from '../../../../../components/InfoViewer';
1
+ import type {
2
+ TColumnDataLifeCycle,
3
+ TColumnTableDescription,
4
+ TEvDescribeSchemeResult,
5
+ TPartitionConfig,
6
+ TTTLSettings,
7
+ } from '../../../../../types/api/schema';
8
+ import type {KeyValueRow} from '../../../../../types/api/query';
9
+ import {EPathType} from '../../../../../types/api/schema';
10
+ import {isNumeric} from '../../../../../utils/utils';
11
+ import {formatBytes, formatNumber} from '../../../../../utils';
12
+ import {formatDurationToShortTimeFormat} from '../../../../../utils/timeParsers';
13
+ import {formatObject, InfoViewerItem} from '../../../../../components/InfoViewer';
4
14
  import {
5
15
  formatFollowerGroupItem,
6
16
  formatPartitionConfigItem,
@@ -8,7 +18,134 @@ import {
8
18
  formatTabletMetricsItem,
9
19
  } from '../../../../../components/InfoViewer/formatters';
10
20
 
11
- export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
21
+ const isInStoreColumnTable = (table: TColumnTableDescription) => {
22
+ // SchemaPresetId could be 0
23
+ return table.SchemaPresetName && table.SchemaPresetId !== undefined;
24
+ };
25
+
26
+ const prepareOlapStats = (olapStats?: KeyValueRow[]) => {
27
+ const Bytes = olapStats?.reduce((acc, el) => {
28
+ const value = isNumeric(el.Bytes) ? Number(el.Bytes) : 0;
29
+ return acc + value;
30
+ }, 0);
31
+ const Rows = olapStats?.reduce((acc, el) => {
32
+ const value = isNumeric(el.Rows) ? Number(el.Rows) : 0;
33
+ return acc + value;
34
+ }, 0);
35
+ const tabletIds = olapStats?.reduce((acc, el) => {
36
+ acc.add(el.TabletId);
37
+ return acc;
38
+ }, new Set());
39
+
40
+ return [
41
+ {label: 'PartCount', value: tabletIds?.size ?? 0},
42
+ {label: 'RowCount', value: formatNumber(Rows) ?? 0},
43
+ {label: 'DataSize', value: formatBytes(Bytes) ?? 0},
44
+ ];
45
+ };
46
+
47
+ const prepareTTL = (ttl: TTTLSettings | TColumnDataLifeCycle) => {
48
+ // ExpireAfterSeconds could be 0
49
+ if (ttl.Enabled && ttl.Enabled.ColumnName && ttl.Enabled.ExpireAfterSeconds !== undefined) {
50
+ const value = `column: '${
51
+ ttl.Enabled.ColumnName
52
+ }', expire after: ${formatDurationToShortTimeFormat(
53
+ ttl.Enabled.ExpireAfterSeconds * 1000,
54
+ 1,
55
+ )}`;
56
+
57
+ return {label: 'TTL for rows', value};
58
+ }
59
+ return undefined;
60
+ };
61
+
62
+ function prepareColumnTableGeneralInfo(columnTable: TColumnTableDescription) {
63
+ const columnTableGeneralInfo: InfoViewerItem[] = [];
64
+
65
+ columnTableGeneralInfo.push({
66
+ label: 'Standalone',
67
+ value: String(!isInStoreColumnTable(columnTable)),
68
+ });
69
+
70
+ if (columnTable.Sharding && columnTable.Sharding.HashSharding) {
71
+ columnTableGeneralInfo.push({label: 'Sharding', value: 'hash'});
72
+ }
73
+
74
+ if (columnTable.TtlSettings) {
75
+ const ttlInfo = prepareTTL(columnTable?.TtlSettings);
76
+ if (ttlInfo) {
77
+ columnTableGeneralInfo.push(ttlInfo);
78
+ }
79
+ }
80
+
81
+ return columnTableGeneralInfo;
82
+ }
83
+
84
+ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings?: TTTLSettings) => {
85
+ const {PartitioningPolicy = {}, FollowerGroups, EnableFilterByKey} = PartitionConfig;
86
+
87
+ const generalTableInfo: InfoViewerItem[] = [];
88
+
89
+ const partitioningBySize = PartitioningPolicy.SizeToSplit
90
+ ? `Enabled, split size: ${formatBytes(PartitioningPolicy.SizeToSplit)}`
91
+ : 'Disabled';
92
+
93
+ const partitioningByLoad = PartitioningPolicy.SplitByLoadSettings?.Enabled
94
+ ? 'Enabled'
95
+ : 'Disabled';
96
+
97
+ generalTableInfo.push(
98
+ {label: 'Partitioning by size', value: partitioningBySize},
99
+ {label: 'Partitioning by load', value: partitioningByLoad},
100
+ {
101
+ label: 'Min number of partitions',
102
+ value: PartitioningPolicy.MinPartitionsCount || 0,
103
+ },
104
+ );
105
+
106
+ if (PartitioningPolicy.MaxPartitionsCount) {
107
+ generalTableInfo.push({
108
+ label: 'Max number of partitions',
109
+ value: PartitioningPolicy.MaxPartitionsCount || 0,
110
+ });
111
+ }
112
+
113
+ if (FollowerGroups && FollowerGroups.length) {
114
+ const {RequireAllDataCenters, FollowerCountPerDataCenter, FollowerCount} =
115
+ FollowerGroups[0];
116
+
117
+ let readReplicasConfig: string;
118
+
119
+ if (RequireAllDataCenters && FollowerCountPerDataCenter) {
120
+ readReplicasConfig = `PER_AZ: ${FollowerCount}`;
121
+ } else {
122
+ readReplicasConfig = `ANY_AZ: ${FollowerCount}`;
123
+ }
124
+
125
+ generalTableInfo.push({label: 'Read replicas (followers)', value: readReplicasConfig});
126
+ }
127
+
128
+ if (TTLSettings) {
129
+ const ttlInfo = prepareTTL(TTLSettings);
130
+ if (ttlInfo) {
131
+ generalTableInfo.push(ttlInfo);
132
+ }
133
+ }
134
+
135
+ generalTableInfo.push({
136
+ label: 'Bloom filter',
137
+ value: EnableFilterByKey ? 'Enabled' : 'Disabled',
138
+ });
139
+
140
+ return generalTableInfo;
141
+ };
142
+
143
+ /** Prepares data for Table, ColumnTable and ColumnStore */
144
+ export const prepareTableInfo = (
145
+ data?: TEvDescribeSchemeResult,
146
+ type?: EPathType,
147
+ olapStats?: KeyValueRow[],
148
+ ) => {
12
149
  if (!data) {
13
150
  return {};
14
151
  }
@@ -18,7 +155,8 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
18
155
  const {
19
156
  TableStats = {},
20
157
  TabletMetrics = {},
21
- Table: {PartitionConfig = {}} = {},
158
+ Table: {PartitionConfig = {}, TTLSettings} = {},
159
+ ColumnTableDescription = {},
22
160
  } = PathDescription;
23
161
 
24
162
  const {
@@ -42,45 +180,62 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
42
180
  RowReads,
43
181
  RangeReads,
44
182
  RangeReadRows,
45
-
46
- ...restTableStats
47
183
  } = TableStats;
48
184
 
49
185
  const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig;
50
186
 
51
- const generalTableInfo = formatObject(formatTableStatsItem, {
52
- PartCount,
53
- RowCount,
54
- DataSize,
55
- IndexSize,
56
- ...restTableStats,
57
- });
187
+ let generalInfo: InfoViewerItem[] = [];
188
+
189
+ switch (type) {
190
+ case EPathType.EPathTypeTable: {
191
+ generalInfo = prepareTableGeneralInfo(PartitionConfig, TTLSettings);
192
+ break;
193
+ }
194
+ case EPathType.EPathTypeColumnTable: {
195
+ generalInfo = prepareColumnTableGeneralInfo(ColumnTableDescription);
196
+ break;
197
+ }
198
+ }
58
199
 
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
- ];
200
+ let tableStatsInfo: InfoViewerItem[][];
201
+
202
+ // There is no TableStats and TabletMetrics for ColumnTables inside ColumnStore
203
+ // Therefore we parse olapStats
204
+ if (type === EPathType.EPathTypeColumnTable && isInStoreColumnTable(ColumnTableDescription)) {
205
+ tableStatsInfo = [prepareOlapStats(olapStats)];
206
+ } else {
207
+ tableStatsInfo = [
208
+ formatObject(formatTableStatsItem, {
209
+ PartCount,
210
+ RowCount,
211
+ DataSize,
212
+ IndexSize,
213
+ }),
214
+ formatObject(formatTableStatsItem, {
215
+ LastAccessTime,
216
+ LastUpdateTime,
217
+ }),
218
+ formatObject(formatTableStatsItem, {
219
+ ImmediateTxCompleted,
220
+ PlannedTxCompleted,
221
+ TxRejectedByOverload,
222
+ TxRejectedBySpace,
223
+ TxCompleteLagMsec,
224
+ InFlightTxCount,
225
+ }),
226
+ formatObject(formatTableStatsItem, {
227
+ RowUpdates,
228
+ RowDeletes,
229
+ RowReads,
230
+ RangeReads,
231
+ RangeReadRows,
232
+ }),
233
+ ];
234
+ }
80
235
 
81
236
  const tabletMetricsInfo = formatObject(formatTabletMetricsItem, TabletMetrics);
82
237
 
83
- let partitionConfigInfo = [];
238
+ let partitionConfigInfo: InfoViewerItem[] = [];
84
239
 
85
240
  if (Array.isArray(FollowerGroups) && FollowerGroups.length > 0) {
86
241
  partitionConfigInfo = formatObject(formatFollowerGroupItem, FollowerGroups[0]);
@@ -92,5 +247,5 @@ export const prepareTableInfo = (data?: TEvDescribeSchemeResult) => {
92
247
  );
93
248
  }
94
249
 
95
- return {generalTableInfo, tableStatsInfo, tabletMetricsInfo, partitionConfigInfo};
250
+ return {generalInfo, tableStatsInfo, tabletMetricsInfo, partitionConfigInfo};
96
251
  };
@@ -25,27 +25,33 @@
25
25
  @include search();
26
26
  }
27
27
 
28
- &__result {
28
+ &__table {
29
29
  overflow: auto;
30
30
  flex-grow: 1;
31
31
 
32
32
  .data-table {
33
- &,
34
- &__table {
35
- width: 100%;
36
- }
37
-
38
- &__td {
39
- vertical-align: top;
40
- white-space: pre;
41
- word-break: break-word;
42
- }
43
-
44
33
  &__row {
45
- max-height: 80px;
46
-
47
34
  cursor: pointer;
48
35
  }
49
36
  }
50
37
  }
38
+
39
+ &__query {
40
+ overflow: hidden;
41
+
42
+ width: 500px;
43
+
44
+ vertical-align: top;
45
+ white-space: pre-wrap;
46
+ text-overflow: ellipsis;
47
+ word-break: break-word;
48
+ }
49
+
50
+ &__user-sid {
51
+ overflow: hidden;
52
+
53
+ max-width: 200px;
54
+
55
+ text-overflow: ellipsis;
56
+ }
51
57
  }