ydb-embedded-ui 3.4.4 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/Icon/Icon.tsx +6 -0
  3. package/dist/components/InfoViewer/InfoViewer.tsx +2 -2
  4. package/dist/components/InfoViewer/formatters/index.ts +0 -1
  5. package/dist/components/InfoViewer/formatters/table.ts +6 -0
  6. package/dist/components/LabelWithPopover/LabelWithPopover.tsx +3 -7
  7. package/dist/components/LagPopoverContent/LagPopoverContent.scss +13 -0
  8. package/dist/components/LagPopoverContent/LagPopoverContent.tsx +19 -0
  9. package/dist/components/LagPopoverContent/index.ts +1 -0
  10. package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss +5 -0
  11. package/dist/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx +31 -0
  12. package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
  13. package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
  14. package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
  15. package/dist/containers/Nodes/Nodes.tsx +2 -6
  16. package/dist/containers/Nodes/NodesTable.scss +11 -10
  17. package/dist/containers/Nodes/getNodesColumns.tsx +29 -24
  18. package/dist/containers/Storage/PDisk/PDisk.scss +2 -0
  19. package/dist/containers/Storage/PDiskPopup/PDiskPopup.tsx +6 -9
  20. package/dist/containers/Storage/Storage.js +12 -5
  21. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -1
  22. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +20 -7
  23. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +43 -7
  24. package/dist/containers/Storage/VDisk/VDisk.tsx +3 -2
  25. package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +4 -2
  26. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
  27. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.scss +0 -8
  28. package/dist/containers/Tenant/Diagnostics/Consumers/Headers/Headers.tsx +3 -10
  29. package/dist/containers/Tenant/Diagnostics/Consumers/i18n/ru.json +1 -1
  30. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
  31. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
  32. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
  33. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/TopicStats.tsx +51 -32
  34. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/en.json +2 -1
  35. package/dist/containers/Tenant/Diagnostics/Overview/TopicStats/i18n/ru.json +2 -1
  36. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.scss +0 -8
  37. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +7 -21
  38. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
  39. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
  40. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
  41. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +1 -0
  42. package/dist/routes.ts +1 -1
  43. package/dist/services/api.d.ts +4 -0
  44. package/dist/services/api.js +3 -3
  45. package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +51 -21
  46. package/dist/store/reducers/executeTopQueries.ts +5 -1
  47. package/dist/store/reducers/{nodesList.js → nodesList.ts} +19 -7
  48. package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
  49. package/dist/store/reducers/settings.js +1 -1
  50. package/dist/store/reducers/storage.js +8 -18
  51. package/dist/types/api/nodesList.ts +25 -0
  52. package/dist/types/api/query.ts +4 -1
  53. package/dist/types/api/schema.ts +523 -3
  54. package/dist/types/common.ts +1 -0
  55. package/dist/types/store/executeQuery.ts +42 -0
  56. package/dist/types/store/nodesList.ts +24 -0
  57. package/dist/types/store/olapStats.ts +14 -0
  58. package/dist/utils/index.js +9 -1
  59. package/dist/utils/nodes.ts +4 -0
  60. package/dist/utils/query.test.ts +42 -29
  61. package/dist/utils/query.ts +34 -22
  62. package/dist/utils/timeParsers/formatDuration.ts +30 -12
  63. package/dist/utils/timeParsers/i18n/en.json +4 -0
  64. package/dist/utils/timeParsers/i18n/ru.json +4 -0
  65. package/dist/utils/tooltip.js +2 -28
  66. package/package.json +1 -1
  67. package/dist/components/InfoViewer/formatters/topicStats.tsx +0 -29
@@ -19,14 +19,6 @@
19
19
  white-space: normal;
20
20
  }
21
21
 
22
- &__lags-popover-content {
23
- max-width: 300px;
24
-
25
- div:nth-child(1) {
26
- margin-bottom: 10px;
27
- }
28
- }
29
-
30
22
  &__messages-popover-content {
31
23
  max-width: 200px;
32
24
  }
@@ -1,7 +1,7 @@
1
1
  import block from 'bem-cn-lite';
2
2
 
3
3
  import {LabelWithPopover} from '../../../../../components/LabelWithPopover';
4
- import {WriteLagImage, ReadLagImage} from '../../../../../components/LagImages';
4
+ import {LagPopoverContent} from '../../../../../components/LagPopoverContent';
5
5
 
6
6
  import {PARTITIONS_COLUMNS_IDS, PARTITIONS_COLUMNS_TITILES} from '../utils/constants';
7
7
 
@@ -28,37 +28,23 @@ export const ReadSessionHeader = () => (
28
28
  export const WriteLagsHeader = () => (
29
29
  <LabelWithPopover
30
30
  className={b('lags')}
31
- headerText={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.READ_LAGS]}
32
- popoverContent={
33
- <div className={b('lags-popover-content')}>
34
- <div>{i18n('lagsPopover.writeLags')}</div>
35
- <div>
36
- <WriteLagImage />
37
- </div>
38
- </div>
39
- }
31
+ text={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.READ_LAGS]}
32
+ popoverContent={<LagPopoverContent text={i18n('lagsPopover.readLags')} type="read" />}
40
33
  />
41
34
  );
42
35
 
43
36
  export const ReadLagsHeader = () => (
44
37
  <LabelWithPopover
45
38
  className={b('lags')}
46
- headerText={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.WRITE_LAGS]}
47
- popoverContent={
48
- <div className={b('lags-popover-content')}>
49
- <div>{i18n('lagsPopover.readLags')}</div>
50
- <div>
51
- <ReadLagImage />
52
- </div>
53
- </div>
54
- }
39
+ text={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.WRITE_LAGS]}
40
+ popoverContent={<LagPopoverContent text={i18n('lagsPopover.writeLags')} type="write" />}
55
41
  />
56
42
  );
57
43
 
58
44
  export const UnreadMessagesHeader = () => (
59
45
  <LabelWithPopover
60
46
  className={b('messages')}
61
- headerText={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.UNREAD_MESSAGES]}
47
+ text={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.UNREAD_MESSAGES]}
62
48
  popoverContent={
63
49
  <div className={b('messages-popover-content')}>{i18n('headers.unread')}</div>
64
50
  }
@@ -68,7 +54,7 @@ export const UnreadMessagesHeader = () => (
68
54
  export const UncommitedMessagesHeader = () => (
69
55
  <LabelWithPopover
70
56
  className={b('messages')}
71
- headerText={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.UNCOMMITED_MESSAGES]}
57
+ text={PARTITIONS_COLUMNS_TITILES[PARTITIONS_COLUMNS_IDS.UNCOMMITED_MESSAGES]}
72
58
  popoverContent={
73
59
  <div className={b('messages-popover-content')}>{i18n('headers.uncommited')}</div>
74
60
  }
@@ -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
  }
@@ -1,5 +1,7 @@
1
1
  import {useCallback, useEffect, useRef, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
+ import {useHistory, useLocation} from 'react-router';
4
+ import qs from 'qs';
3
5
  import cn from 'bem-cn-lite';
4
6
 
5
7
  import DataTable, {Column, Settings} from '@gravity-ui/react-data-table';
@@ -21,13 +23,14 @@ import type {EPathType} from '../../../../types/api/schema';
21
23
  import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
22
24
  import type {IQueryResult} from '../../../../types/store/query';
23
25
 
24
- import {formatDateTime} from '../../../../utils';
26
+ import {formatDateTime, formatNumber} from '../../../../utils';
25
27
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
26
28
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
27
29
  import {prepareQueryError} from '../../../../utils/query';
30
+ import routes, {createHref} from '../../../../routes';
28
31
 
29
32
  import {isColumnEntityType} from '../../utils/schema';
30
- import {TenantGeneralTabsIds} from '../../TenantPages';
33
+ import {TenantGeneralTabsIds, TenantTabsGroups} from '../../TenantPages';
31
34
 
32
35
  import i18n from './i18n';
33
36
  import './TopQueries.scss';
@@ -43,19 +46,41 @@ const MAX_QUERY_HEIGHT = 10;
43
46
  const COLUMNS: Column<KeyValueRow>[] = [
44
47
  {
45
48
  name: 'CPUTimeUs',
46
- width: 140,
47
- sortAccessor: (row) => Number(row['CPUTimeUs']),
49
+ sortAccessor: (row) => Number(row.CPUTimeUs),
50
+ align: DataTable.RIGHT,
48
51
  },
49
52
  {
50
53
  name: 'QueryText',
51
54
  width: 500,
52
55
  sortable: false,
53
- render: ({value}) => <TruncatedQuery value={value} maxQueryHeight={MAX_QUERY_HEIGHT} />,
56
+ render: ({row}) => (
57
+ <div className={b('query')}>
58
+ <TruncatedQuery value={row.QueryText} maxQueryHeight={MAX_QUERY_HEIGHT} />
59
+ </div>
60
+ ),
61
+ },
62
+ {
63
+ name: 'EndTime',
64
+ render: ({row}) => formatDateTime(new Date(row.EndTime as string).getTime()),
65
+ align: DataTable.RIGHT,
66
+ },
67
+ {
68
+ name: 'ReadRows',
69
+ render: ({row}) => formatNumber(row.ReadRows),
70
+ sortAccessor: (row) => Number(row.ReadRows),
71
+ align: DataTable.RIGHT,
72
+ },
73
+ {
74
+ name: 'ReadBytes',
75
+ render: ({row}) => formatNumber(row.ReadBytes),
76
+ sortAccessor: (row) => Number(row.ReadBytes),
77
+ align: DataTable.RIGHT,
54
78
  },
55
79
  {
56
- name: 'IntervalEnd',
57
- width: 140,
58
- render: ({value}) => formatDateTime(new Date(value as string).getTime()),
80
+ name: 'UserSID',
81
+ render: ({row}) => <div className={b('user-sid')}>{row.UserSID || '–'}</div>,
82
+ sortAccessor: (row) => String(row.UserSID),
83
+ align: DataTable.LEFT,
59
84
  },
60
85
  ];
61
86
 
@@ -65,8 +90,10 @@ interface TopQueriesProps {
65
90
  type?: EPathType;
66
91
  }
67
92
 
68
- export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
93
+ export const TopQueries = ({path, type}: TopQueriesProps) => {
69
94
  const dispatch = useDispatch();
95
+ const location = useLocation();
96
+ const history = useHistory();
70
97
 
71
98
  const {autorefresh} = useTypedSelector((state) => state.schema);
72
99
 
@@ -144,9 +171,19 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
144
171
  const {QueryText: input} = row;
145
172
 
146
173
  dispatch(changeUserInput({input}));
147
- changeSchemaTab(TenantGeneralTabsIds.query);
174
+
175
+ const queryParams = qs.parse(location.search, {
176
+ ignoreQueryPrefix: true,
177
+ });
178
+
179
+ const queryPath = createHref(routes.tenant, undefined, {
180
+ ...queryParams,
181
+ [TenantTabsGroups.general]: TenantGeneralTabsIds.query,
182
+ });
183
+
184
+ history.push(queryPath);
148
185
  },
149
- [changeSchemaTab, dispatch],
186
+ [dispatch, history, location],
150
187
  );
151
188
 
152
189
  const handleTextSearchUpdate = (text: string) => {
@@ -179,7 +216,7 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
179
216
  }
180
217
 
181
218
  return (
182
- <div className={b('result')}>
219
+ <div className={b('table')}>
183
220
  <DataTable
184
221
  columns={COLUMNS}
185
222
  data={data}
@@ -20,6 +20,7 @@ import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema
20
20
  import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
21
21
 
22
22
  import type {EPathType} from '../../../../types/api/schema';
23
+ import type {CellValue, KeyValueRow} from '../../../../types/api/query';
23
24
 
24
25
  import {formatDateTime, formatNumber} from '../../../../utils';
25
26
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
@@ -57,10 +58,17 @@ const tableColumnsNames = {
57
58
  IntervalEnd: 'IntervalEnd',
58
59
  };
59
60
 
60
- function prepareCPUWorkloadValue(value: string) {
61
+ function prepareCPUWorkloadValue(value: string | number) {
61
62
  return `${(Number(value) * 100).toFixed(2)}%`;
62
63
  }
63
64
 
65
+ function prepareDateTimeValue(value: CellValue) {
66
+ if (!value) {
67
+ return '–';
68
+ }
69
+ return formatDateTime(new Date(value).getTime());
70
+ }
71
+
64
72
  function stringToDataTableSortOrder(value: string): SortOrder[] | undefined {
65
73
  return value
66
74
  ? value.split(',').map((columnId) => ({
@@ -190,16 +198,17 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
190
198
  };
191
199
  };
192
200
 
193
- const columns: Column<any>[] = [
201
+ const columns: Column<KeyValueRow>[] = [
194
202
  {
195
203
  name: tableColumnsNames.Path,
196
- render: ({value: relativeNodePath}) => {
204
+ render: ({row}) => {
205
+ // row.Path - relative schema path
197
206
  return (
198
207
  <span
199
- onClick={onSchemaClick(tenantPath + relativeNodePath)}
208
+ onClick={onSchemaClick(tenantPath + row.Path)}
200
209
  className={bLink({view: 'normal'})}
201
210
  >
202
- {relativeNodePath as string}
211
+ {row.Path}
203
212
  </span>
204
213
  );
205
214
  },
@@ -207,25 +216,28 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
207
216
  },
208
217
  {
209
218
  name: tableColumnsNames.CPUCores,
210
- render: ({value}) => {
211
- return prepareCPUWorkloadValue(value as string);
219
+ render: ({row}) => {
220
+ return prepareCPUWorkloadValue(row.CPUCores || 0);
212
221
  },
213
222
  align: DataTable.RIGHT,
214
223
  },
215
224
  {
216
225
  name: tableColumnsNames.DataSize,
217
226
  header: 'DataSize (B)',
218
- render: ({value}) => {
219
- return formatNumber(value as number);
227
+ render: ({row}) => {
228
+ return formatNumber(row.DataSize);
220
229
  },
221
230
  align: DataTable.RIGHT,
222
231
  },
223
232
  {
224
233
  name: tableColumnsNames.TabletId,
225
- render: ({value}) => {
234
+ render: ({row}) => {
235
+ if (!row.TabletId) {
236
+ return '–';
237
+ }
226
238
  return (
227
- <InternalLink to={createHref(routes.tablet, {id: value})}>
228
- {value as string}
239
+ <InternalLink to={createHref(routes.tablet, {id: row.TabletId})}>
240
+ {row.TabletId}
229
241
  </InternalLink>
230
242
  );
231
243
  },
@@ -233,10 +245,13 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
233
245
  },
234
246
  {
235
247
  name: tableColumnsNames.NodeId,
236
- render: ({value: nodeId}) => {
248
+ render: ({row}) => {
249
+ if (!row.NodeId) {
250
+ return '–';
251
+ }
237
252
  return (
238
- <InternalLink to={getDefaultNodePath(nodeId as string)}>
239
- {nodeId as string}
253
+ <InternalLink to={getDefaultNodePath(row.NodeId)}>
254
+ {row.NodeId}
240
255
  </InternalLink>
241
256
  );
242
257
  },
@@ -245,7 +260,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
245
260
  },
246
261
  {
247
262
  name: tableColumnsNames.InFlightTxCount,
248
- render: ({value}) => formatNumber(value as number),
263
+ render: ({row}) => formatNumber(row.InFlightTxCount),
249
264
  align: DataTable.RIGHT,
250
265
  sortable: false,
251
266
  },
@@ -255,12 +270,16 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
255
270
  // after NodeId
256
271
  columns.splice(5, 0, {
257
272
  name: tableColumnsNames.PeakTime,
258
- render: ({value}) => formatDateTime(new Date(value as string).valueOf()),
273
+ render: ({row}) => {
274
+ return prepareDateTimeValue(row.PeakTime);
275
+ },
259
276
  sortable: false,
260
277
  });
261
278
  columns.push({
262
279
  name: tableColumnsNames.IntervalEnd,
263
- render: ({value}) => formatDateTime(new Date(value as string).getTime()),
280
+ render: ({row}) => {
281
+ return prepareDateTimeValue(row.IntervalEnd);
282
+ },
264
283
  });
265
284
  }
266
285
 
@@ -544,6 +544,7 @@ function QueryEditor(props) {
544
544
  </Button>
545
545
  <DropdownMenu
546
546
  items={menuItems}
547
+ popupClassName={b('select-query-action-popup')}
547
548
  switcher={
548
549
  <Button
549
550
  view="action"
package/dist/routes.ts CHANGED
@@ -28,7 +28,7 @@ export const CLUSTER_PAGES = {
28
28
 
29
29
  export function createHref(
30
30
  route: string,
31
- params?: object,
31
+ params?: Record<string, string | number>,
32
32
  query: Record<string | number, string | number | string[] | number[] | undefined> = {},
33
33
  ) {
34
34
  let extendedQuery = query;
@@ -77,6 +77,10 @@ interface Window {
77
77
  consumer?: string;
78
78
  }) => Promise<import('../types/api/consumer').DescribeConsumerResult>;
79
79
  getHostInfo: () => Promise<import('../types/api/systemState').TEvSystemStateResponse>;
80
+ getNodeInfo: (
81
+ id?: string,
82
+ ) => Promise<import('../types/api/systemState').TEvSystemStateResponse>;
83
+ getNodesList: () => Promise<import('../types/api/nodesList').TEvNodesInfo>;
80
84
  [method: string]: Function;
81
85
  };
82
86
  }
@@ -96,9 +96,9 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
96
96
  enums: true,
97
97
  backup: false,
98
98
  private: true,
99
- partition_config: false,
100
- partition_stats: false,
101
- partitioning_info: false,
99
+ partition_config: true,
100
+ partition_stats: true,
101
+ partitioning_info: true,
102
102
  subs: 1,
103
103
  },
104
104
  {concurrentId: concurrentId || `getSchema|${path}`},
@@ -1,13 +1,25 @@
1
- import {createRequestActionTypes, createApiRequest} from '../utils';
2
- import '../../services/api';
1
+ import type {Reducer} from 'redux';
2
+
3
+ import type {Actions} from '../../types/api/query';
4
+ import type {
5
+ ExecuteQueryAction,
6
+ ExecuteQueryState,
7
+ MonacoHotKeyAction,
8
+ RunAction,
9
+ } from '../../types/store/executeQuery';
3
10
  import {getValueFromLS, parseJson} from '../../utils/utils';
4
11
  import {QUERIES_HISTORY_KEY, QUERY_INITIAL_RUN_ACTION_KEY} from '../../utils/constants';
5
12
  import {parseQueryAPIExecuteResponse} from '../../utils/query';
13
+ import '../../services/api';
14
+
15
+ import {createRequestActionTypes, createApiRequest} from '../utils';
16
+
6
17
  import {readSavedSettingsValue} from './settings';
7
18
 
8
19
  const MAXIMUM_QUERIES_IN_HISTORY = 20;
9
20
 
10
- const SEND_QUERY = createRequestActionTypes('query', 'SEND_QUERY');
21
+ export const SEND_QUERY = createRequestActionTypes('query', 'SEND_QUERY');
22
+
11
23
  const CHANGE_USER_INPUT = 'query/CHANGE_USER_INPUT';
12
24
  const SAVE_QUERY_TO_HISTORY = 'query/SAVE_QUERY_TO_HISTORY';
13
25
  const GO_TO_PREVIOUS_QUERY = 'query/GO_TO_PREVIOUS_QUERY';
@@ -15,21 +27,21 @@ const GO_TO_NEXT_QUERY = 'query/GO_TO_NEXT_QUERY';
15
27
  const SELECT_RUN_ACTION = 'query/SELECT_RUN_ACTION';
16
28
  const MONACO_HOT_KEY = 'query/MONACO_HOT_KEY';
17
29
 
18
- const queriesHistoryInitial = parseJson(getValueFromLS(QUERIES_HISTORY_KEY, '[]'));
30
+ const queriesHistoryInitial: string[] = parseJson(getValueFromLS(QUERIES_HISTORY_KEY, '[]'));
19
31
 
20
32
  const sliceLimit = queriesHistoryInitial.length - MAXIMUM_QUERIES_IN_HISTORY;
21
33
 
22
34
  export const RUN_ACTIONS_VALUES = {
23
35
  script: 'execute-script',
24
36
  scan: 'execute-scan',
25
- };
37
+ } as const;
26
38
 
27
39
  export const MONACO_HOT_KEY_ACTIONS = {
28
40
  sendQuery: 'sendQuery',
29
41
  goPrev: 'goPrev',
30
42
  goNext: 'goNext',
31
43
  getExplain: 'getExplain',
32
- };
44
+ } as const;
33
45
 
34
46
  const initialState = {
35
47
  loading: false,
@@ -45,7 +57,10 @@ const initialState = {
45
57
  monacoHotKey: null,
46
58
  };
47
59
 
48
- const executeQuery = (state = initialState, action) => {
60
+ const executeQuery: Reducer<ExecuteQueryState, ExecuteQueryAction> = (
61
+ state = initialState,
62
+ action,
63
+ ) => {
49
64
  switch (action.type) {
50
65
  case SEND_QUERY.REQUEST: {
51
66
  return {
@@ -141,51 +156,66 @@ const executeQuery = (state = initialState, action) => {
141
156
  }
142
157
  };
143
158
 
144
- export const sendQuery = ({query, database, action}) => {
159
+ export const sendQuery = ({
160
+ query,
161
+ database,
162
+ action,
163
+ }: {
164
+ query: string;
165
+ database: string;
166
+ action: Actions;
167
+ }) => {
145
168
  return createApiRequest({
146
- request: window.api.sendQuery({schema: 'modern', query, database, action, stats: 'profile'}),
169
+ request: window.api.sendQuery({
170
+ schema: 'modern',
171
+ query,
172
+ database,
173
+ action,
174
+ stats: 'profile',
175
+ }),
147
176
  actions: SEND_QUERY,
148
177
  dataHandler: parseQueryAPIExecuteResponse,
149
178
  });
150
179
  };
151
180
 
152
- export const saveQueryToHistory = (query) => {
181
+ export const saveQueryToHistory = (query: string) => {
153
182
  return {
154
183
  type: SAVE_QUERY_TO_HISTORY,
155
184
  data: query,
156
- };
185
+ } as const;
157
186
  };
158
187
 
159
- export const selectRunAction = (value) => {
188
+ export const selectRunAction = (value: RunAction) => {
160
189
  return {
161
190
  type: SELECT_RUN_ACTION,
162
191
  data: value,
163
- };
192
+ } as const;
164
193
  };
165
194
 
166
195
  export const goToPreviousQuery = () => {
167
196
  return {
168
197
  type: GO_TO_PREVIOUS_QUERY,
169
- };
198
+ } as const;
170
199
  };
171
200
 
172
201
  export const goToNextQuery = () => {
173
202
  return {
174
203
  type: GO_TO_NEXT_QUERY,
175
- };
204
+ } as const;
176
205
  };
177
206
 
178
- export const changeUserInput = ({input}) => {
179
- return (dispatch) => {
180
- dispatch({type: CHANGE_USER_INPUT, data: {input}});
181
- };
207
+ export const changeUserInput = ({input}: {input: string}) => {
208
+ return {
209
+ type: CHANGE_USER_INPUT,
210
+ data: {input},
211
+ } as const;
182
212
  };
183
213
 
184
- export const setMonacoHotKey = (value) => {
214
+ export const setMonacoHotKey = (value: MonacoHotKeyAction) => {
185
215
  return {
186
216
  type: MONACO_HOT_KEY,
187
217
  data: value,
188
- };
218
+ } as const;
189
219
  };
190
220
 
191
221
  export default executeQuery;
@@ -66,7 +66,11 @@ const getQueryText = (path: string, filters?: ITopQueriesFilters) => {
66
66
  SELECT
67
67
  CPUTime as CPUTimeUs,
68
68
  QueryText,
69
- IntervalEnd
69
+ IntervalEnd,
70
+ EndTime,
71
+ ReadRows,
72
+ ReadBytes,
73
+ UserSID
70
74
  FROM \`${path}/.sys/top_queries_by_cpu_time_one_hour\`
71
75
  WHERE ${filterConditions || 'true'}
72
76
  `;
@@ -1,11 +1,19 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import type {
4
+ NodesListState,
5
+ NodesListAction,
6
+ NodesListRootStateSlice,
7
+ NodesMap,
8
+ } from '../../types/store/nodesList';
1
9
  import '../../services/api';
2
10
  import {createRequestActionTypes, createApiRequest} from '../utils';
3
11
 
4
- const FETCH_NODES_LIST = createRequestActionTypes('tenants', 'FETCH_NODES_LIST');
12
+ export const FETCH_NODES_LIST = createRequestActionTypes('nodesList', 'FETCH_NODES_LIST');
5
13
 
6
14
  const initialState = {loading: true, wasLoaded: false, data: []};
7
15
 
8
- const nodesList = function (state = initialState, action) {
16
+ const nodesList: Reducer<NodesListState, NodesListAction> = (state = initialState, action) => {
9
17
  switch (action.type) {
10
18
  case FETCH_NODES_LIST.REQUEST: {
11
19
  return {
@@ -36,13 +44,17 @@ const nodesList = function (state = initialState, action) {
36
44
 
37
45
  export function getNodesList() {
38
46
  return createApiRequest({
39
- request: window.api.getNodeInfo(),
47
+ request: window.api.getNodesList(),
40
48
  actions: FETCH_NODES_LIST,
41
- dataHandler: (data) => {
42
- const {SystemStateInfo: nodes = []} = data;
43
- return nodes;
44
- },
45
49
  });
46
50
  }
47
51
 
52
+ export const selectNodesMap = (state: NodesListRootStateSlice) =>
53
+ state.nodesList.data?.reduce<NodesMap>((nodesMap, node) => {
54
+ if (node.Id && node.Host) {
55
+ nodesMap.set(node.Id, node.Host);
56
+ }
57
+ return nodesMap;
58
+ }, new Map());
59
+
48
60
  export default nodesList;