ydb-embedded-ui 3.4.5 → 3.5.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.
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
  }