ydb-embedded-ui 2.6.0 → 3.0.1

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 (42) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/components/ClusterInfo/ClusterInfo.tsx +1 -1
  3. package/dist/components/InfoViewer/InfoViewer.tsx +1 -1
  4. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +5 -2
  5. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +6 -5
  6. package/dist/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +5 -2
  7. package/dist/components/ProblemFilter/ProblemFilter.tsx +18 -0
  8. package/dist/components/ProblemFilter/index.ts +1 -0
  9. package/dist/components/UptimeFIlter/UptimeFilter.tsx +4 -3
  10. package/dist/containers/Nodes/Nodes.js +2 -2
  11. package/dist/containers/NodesViewer/NodesViewer.js +2 -2
  12. package/dist/containers/Pool/Pool.js +2 -2
  13. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +2 -3
  14. package/dist/containers/Tenant/Diagnostics/Network/Network.js +2 -2
  15. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -9
  16. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +6 -3
  17. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.scss +0 -4
  18. package/dist/containers/Tenant/Diagnostics/TopShards/{TopShards.js → TopShards.tsx} +95 -119
  19. package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +1 -0
  20. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +35 -22
  21. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.scss +8 -0
  22. package/dist/containers/Tenant/Tenant.tsx +1 -1
  23. package/dist/containers/Tenant/utils/index.ts +8 -0
  24. package/dist/containers/Tenant/utils/schema.ts +45 -0
  25. package/dist/containers/Tenants/Tenants.js +2 -2
  26. package/dist/services/api.d.ts +3 -0
  27. package/dist/services/api.js +1 -1
  28. package/dist/store/reducers/{nodes.js → nodes.ts} +20 -14
  29. package/dist/store/reducers/{shardsWorkload.js → shardsWorkload.ts} +28 -13
  30. package/dist/store/reducers/{tooltip.js → tooltip.ts} +28 -11
  31. package/dist/types/api/nodes.ts +3 -3
  32. package/dist/types/api/schema.ts +1 -1
  33. package/dist/types/api/tenant.ts +131 -0
  34. package/dist/types/store/nodes.ts +32 -0
  35. package/dist/types/store/shardsWorkload.ts +19 -0
  36. package/dist/types/store/tooltip.ts +25 -0
  37. package/dist/utils/constants.ts +2 -0
  38. package/dist/utils/nodes.ts +4 -4
  39. package/dist/utils/tooltip.js +8 -6
  40. package/package.json +4 -3
  41. package/dist/components/ProblemFilter/ProblemFilter.js +0 -24
  42. package/dist/utils/actionsConstants.js +0 -4
@@ -1,27 +1,34 @@
1
1
  import {useState, useContext, useEffect, useMemo} from 'react';
2
+ import {useDispatch} from 'react-redux';
2
3
  import cn from 'bem-cn-lite';
3
- import {connect} from 'react-redux';
4
+
5
+ import DataTable, {Column, Settings, SortOrder} from '@yandex-cloud/react-data-table';
4
6
  import {Loader} from '@gravity-ui/uikit';
5
- import DataTable from '@yandex-cloud/react-data-table';
6
7
 
7
8
  import InternalLink from '../../../../components/InternalLink/InternalLink';
8
9
 
10
+ import HistoryContext from '../../../../contexts/HistoryContext';
11
+
9
12
  import routes, {createHref} from '../../../../routes';
13
+
10
14
  import {sendShardQuery, setShardQueryOptions} from '../../../../store/reducers/shardsWorkload';
11
15
  import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
12
- import {AutoFetcher} from '../../../../utils/autofetcher';
13
- import HistoryContext from '../../../../contexts/HistoryContext';
16
+
17
+ import type {EPathType} from '../../../../types/api/schema';
18
+
14
19
  import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
15
- import {isColumnEntityType} from '../../utils/schema';
16
- import {prepareQueryError} from '../../../../utils/query';
20
+ import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
17
21
  import {i18n} from '../../../../utils/i18n';
22
+ import {prepareQueryError} from '../../../../utils/query';
23
+
24
+ import {isColumnEntityType} from '../../utils/schema';
18
25
 
19
26
  import './TopShards.scss';
20
27
 
21
28
  const b = cn('top-shards');
22
29
  const bLink = cn('yc-link');
23
30
 
24
- const TABLE_SETTINGS = {
31
+ const TABLE_SETTINGS: Settings = {
25
32
  ...DEFAULT_TABLE_SETTINGS,
26
33
  dynamicRender: false, // no more than 20 rows
27
34
  externalSort: true,
@@ -36,121 +43,108 @@ const tableColumnsNames = {
36
43
  Path: 'Path',
37
44
  };
38
45
 
39
- const autofetcher = new AutoFetcher();
40
-
41
- function prepareCPUWorkloadValue(value) {
42
- return `${(value * 100).toFixed(2)}%`;
46
+ function prepareCPUWorkloadValue(value: string) {
47
+ return `${(Number(value) * 100).toFixed(2)}%`;
43
48
  }
44
49
 
45
- function prepareDateSizeValue(value) {
50
+ function prepareDateSizeValue(value: number) {
46
51
  return new Intl.NumberFormat(i18n.lang).format(value);
47
52
  }
48
53
 
49
- function stringToDataTableSortOrder(value) {
50
- return (
51
- value &&
52
- value.split(',').map((columnId) => ({
53
- columnId,
54
- order: DataTable.DESCENDING,
55
- }))
56
- );
54
+ function stringToDataTableSortOrder(value: string): SortOrder[] | undefined {
55
+ return value
56
+ ? value.split(',').map((columnId) => ({
57
+ columnId,
58
+ order: DataTable.DESCENDING,
59
+ }))
60
+ : undefined;
57
61
  }
58
62
 
59
- function stringToQuerySortOrder(value) {
60
- return (
61
- value &&
62
- value.split(',').map((columnId) => ({
63
- columnId,
64
- order: 'DESC',
65
- }))
66
- );
63
+ function stringToQuerySortOrder(value: string) {
64
+ return value
65
+ ? value.split(',').map((columnId) => ({
66
+ columnId,
67
+ order: 'DESC',
68
+ }))
69
+ : undefined;
67
70
  }
68
71
 
69
- function dataTableToStringSortOrder(value = []) {
70
- return value.map(({columnId}) => columnId).join(',');
72
+ function dataTableToStringSortOrder(value: SortOrder | SortOrder[] = []) {
73
+ const sortOrders = Array.isArray(value) ? value : [value];
74
+ return sortOrders.map(({columnId}) => columnId).join(',');
71
75
  }
72
76
 
73
- function TopShards({
74
- sendShardQuery,
75
- currentSchemaPath,
76
- path,
77
- loading,
78
- data,
79
- error,
80
- setCurrentSchemaPath,
81
- getSchema,
82
- autorefresh,
83
- wasLoaded,
84
- setShardQueryOptions,
85
- type,
86
- }) {
87
- const [sortOrder, setSortOrder] = useState(tableColumnsNames.CPUCores);
77
+ interface TopShardsProps {
78
+ tenantPath: string;
79
+ type?: EPathType;
80
+ }
88
81
 
89
- useEffect(() => {
90
- autofetcher.stop();
82
+ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
83
+ const dispatch = useDispatch();
84
+
85
+ const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
86
+
87
+ const {
88
+ loading,
89
+ data: {result: data = undefined} = {},
90
+ error,
91
+ wasLoaded,
92
+ } = useTypedSelector((state) => state.shardsWorkload);
91
93
 
92
- if (autorefresh) {
93
- autofetcher.start();
94
- autofetcher.fetch(() =>
94
+ const [sortOrder, setSortOrder] = useState(tableColumnsNames.CPUCores);
95
+
96
+ useAutofetcher(
97
+ () => {
98
+ dispatch(
95
99
  sendShardQuery({
96
- database: path,
100
+ database: tenantPath,
97
101
  path: currentSchemaPath,
98
102
  sortOrder: stringToQuerySortOrder(sortOrder),
99
103
  }),
100
104
  );
101
- }
102
-
103
- return () => {
104
- autofetcher.stop();
105
- };
106
- }, [autorefresh, currentSchemaPath, path, sendShardQuery, sortOrder]);
105
+ },
106
+ [dispatch, currentSchemaPath, tenantPath, sortOrder],
107
+ autorefresh,
108
+ );
107
109
 
108
110
  // don't show loader for requests triggered by table sort, only for path change
109
111
  useEffect(() => {
110
- setShardQueryOptions({
111
- wasLoaded: false,
112
- data: undefined,
113
- });
114
- }, [currentSchemaPath, path, setShardQueryOptions]);
115
-
116
- useEffect(() => {
117
- sendShardQuery({
118
- database: path,
119
- path: currentSchemaPath,
120
- sortOrder: stringToQuerySortOrder(sortOrder),
121
- });
122
- }, [currentSchemaPath, path, sendShardQuery, sortOrder]);
112
+ dispatch(
113
+ setShardQueryOptions({
114
+ wasLoaded: false,
115
+ data: undefined,
116
+ }),
117
+ );
118
+ }, [dispatch, currentSchemaPath, tenantPath]);
123
119
 
124
120
  const history = useContext(HistoryContext);
125
121
 
126
- const onSchemaClick = (schemaPath) => {
127
- return () => {
128
- setCurrentSchemaPath(schemaPath);
129
- getSchema({path: schemaPath});
130
- history.go(0);
131
- };
132
- };
133
-
134
- const onSort = (newSortOrder) => {
122
+ const onSort = (newSortOrder?: SortOrder | SortOrder[]) => {
135
123
  // omit information about sort order to disable ASC order, only DESC makes sense for top shards
136
124
  // use a string (and not the DataTable default format) to prevent reference change,
137
125
  // which would cause an excess state change, to avoid repeating requests
138
126
  setSortOrder(dataTableToStringSortOrder(newSortOrder));
139
127
  };
140
128
 
141
- const tableColumns = useMemo(() => {
129
+ const tableColumns: Column<any>[] = useMemo(() => {
130
+ const onSchemaClick = (schemaPath: string) => {
131
+ return () => {
132
+ dispatch(setCurrentSchemaPath(schemaPath));
133
+ dispatch(getSchema({path: schemaPath}));
134
+ history.go(0);
135
+ };
136
+ };
137
+
142
138
  return [
143
139
  {
144
140
  name: tableColumnsNames.Path,
145
- // eslint-disable-next-line
146
- render: ({value}) => {
141
+ render: ({value: relativeNodePath}) => {
147
142
  return (
148
143
  <span
149
- // tenant name is substringed out in sql query but is needed here
150
- onClick={onSchemaClick(path + value)}
144
+ onClick={onSchemaClick(tenantPath + relativeNodePath)}
151
145
  className={bLink({view: 'normal'})}
152
146
  >
153
- {value}
147
+ {relativeNodePath as string}
154
148
  </span>
155
149
  );
156
150
  },
@@ -158,9 +152,8 @@ function TopShards({
158
152
  },
159
153
  {
160
154
  name: tableColumnsNames.CPUCores,
161
- // eslint-disable-next-line
162
155
  render: ({value}) => {
163
- return prepareCPUWorkloadValue(value);
156
+ return prepareCPUWorkloadValue(value as string);
164
157
  },
165
158
  align: DataTable.RIGHT,
166
159
  },
@@ -168,24 +161,23 @@ function TopShards({
168
161
  name: tableColumnsNames.DataSize,
169
162
  header: 'DataSize (B)',
170
163
  render: ({value}) => {
171
- return prepareDateSizeValue(value);
164
+ return prepareDateSizeValue(value as number);
172
165
  },
173
166
  align: DataTable.RIGHT,
174
167
  },
175
168
  {
176
169
  name: tableColumnsNames.TabletId,
177
- // eslint-disable-next-line
178
170
  render: ({value}) => {
179
171
  return (
180
172
  <InternalLink to={createHref(routes.tablet, {id: value})}>
181
- {value}
173
+ {value as string}
182
174
  </InternalLink>
183
175
  );
184
176
  },
185
177
  sortable: false,
186
178
  },
187
179
  ];
188
- }, []);
180
+ }, [dispatch, history, tenantPath]);
189
181
 
190
182
  const renderLoader = () => {
191
183
  return (
@@ -196,51 +188,35 @@ function TopShards({
196
188
  };
197
189
 
198
190
  const renderContent = () => {
199
- if (isColumnEntityType(type)) {
191
+ if (loading && !wasLoaded) {
192
+ return renderLoader();
193
+ }
194
+
195
+ if (!data || data.length === 0 || isColumnEntityType(type)) {
200
196
  return 'No data';
201
197
  }
198
+
202
199
  if (error && !error.isCancelled) {
203
200
  return prepareQueryError(error);
204
201
  }
205
202
 
206
- return data && data.length > 0 ? (
203
+ return (
207
204
  <div className={b('table')}>
208
205
  <DataTable
209
206
  columns={tableColumns}
210
207
  data={data}
211
208
  settings={TABLE_SETTINGS}
212
- className={b('table')}
213
209
  theme="yandex-cloud"
214
210
  onSort={onSort}
215
211
  sortOrder={stringToDataTableSortOrder(sortOrder)}
216
212
  />
217
213
  </div>
218
- ) : (
219
- data
220
214
  );
221
215
  };
222
216
 
223
- return loading && !wasLoaded ? renderLoader() : <div className={b()}>{renderContent()}</div>;
224
- }
225
-
226
- const mapStateToProps = (state) => {
227
- const {loading, data = {}, error, wasLoaded} = state.shardsWorkload;
228
- const {autorefresh} = state.schema;
229
- return {
230
- loading,
231
- data: data.result,
232
- error,
233
- currentSchemaPath: state.schema?.currentSchema?.Path,
234
- autorefresh,
235
- wasLoaded,
236
- };
237
- };
238
-
239
- const mapDispatchToProps = {
240
- sendShardQuery,
241
- setCurrentSchemaPath,
242
- getSchema,
243
- setShardQueryOptions,
217
+ return (
218
+ <div className={b()}>
219
+ {renderContent()}
220
+ </div>
221
+ );
244
222
  };
245
-
246
- export default connect(mapStateToProps, mapDispatchToProps)(TopShards);
@@ -0,0 +1 @@
1
+ export * from './TopShards';
@@ -1,12 +1,15 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cn from 'bem-cn-lite';
4
- import './SchemaInfoViewer.scss';
5
4
 
6
5
  import {formatCPU, formatBytes, formatNumber, formatBps, formatDateTime} from '../../../../utils';
7
6
 
8
7
  import {InfoViewer, createInfoFormatter} from '../../../../components/InfoViewer';
9
8
 
9
+ import {getEntityName} from '../../utils';
10
+
11
+ import './SchemaInfoViewer.scss';
12
+
10
13
  const b = cn('schema-info-viewer');
11
14
 
12
15
  const formatTabletMetricsItem = createInfoFormatter({
@@ -68,6 +71,8 @@ class SchemaInfoViewer extends React.Component {
68
71
 
69
72
  renderContent(data) {
70
73
  const {PathDescription = {}} = data;
74
+ const entityName = getEntityName(PathDescription);
75
+
71
76
  const {
72
77
  TableStats = {},
73
78
  TabletMetrics = {},
@@ -99,13 +104,15 @@ class SchemaInfoViewer extends React.Component {
99
104
  } = TableStats;
100
105
  const {FollowerGroups, FollowerCount, CrossDataCenterFollowerCount} = PartitionConfig;
101
106
 
107
+ const generalTableInfo = formatTableStats({
108
+ PartCount,
109
+ RowCount,
110
+ DataSize,
111
+ IndexSize,
112
+ ...restTableStats,
113
+ });
114
+
102
115
  const tableStatsInfo = [
103
- formatTableStats({
104
- PartCount,
105
- RowCount,
106
- DataSize,
107
- IndexSize,
108
- }),
109
116
  formatTableStats({
110
117
  LastAccessTime,
111
118
  LastUpdateTime,
@@ -125,7 +132,6 @@ class SchemaInfoViewer extends React.Component {
125
132
  RangeReads,
126
133
  RangeReadRows,
127
134
  }),
128
- formatTableStats(restTableStats),
129
135
  ];
130
136
 
131
137
  const tabletMetricsInfo = Object.keys(TabletMetrics).map((key) =>
@@ -151,24 +157,30 @@ class SchemaInfoViewer extends React.Component {
151
157
  );
152
158
  }
153
159
 
154
- if ([tabletMetricsInfo, partitionConfigInfo, tableStatsInfo.flat()].flat().length === 0) {
155
- return <div className={b('item')}>Empty</div>;
160
+ if (
161
+ [generalTableInfo, tabletMetricsInfo, partitionConfigInfo, tableStatsInfo.flat()].flat()
162
+ .length === 0
163
+ ) {
164
+ return <div className={b('title')}>{entityName}</div>;
156
165
  }
157
166
 
158
167
  return (
159
- <div className={b('row')}>
160
- {tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
168
+ <div>
169
+ <div>{this.renderItem(generalTableInfo, entityName)}</div>
170
+ <div className={b('row')}>
171
+ {tabletMetricsInfo.length > 0 || partitionConfigInfo.length > 0 ? (
172
+ <div className={b('col')}>
173
+ {this.renderItem(tabletMetricsInfo, 'Tablet Metrics')}
174
+ {this.renderItem(partitionConfigInfo, 'Partition Config')}
175
+ </div>
176
+ ) : null}
161
177
  <div className={b('col')}>
162
- {this.renderItem(tabletMetricsInfo, 'Tablet Metrics')}
163
- {this.renderItem(partitionConfigInfo, 'Partition Config')}
178
+ {tableStatsInfo.map((info, index) => (
179
+ <React.Fragment key={index}>
180
+ {this.renderItem(info, index === 0 ? 'Table Stats' : undefined)}
181
+ </React.Fragment>
182
+ ))}
164
183
  </div>
165
- ) : null}
166
- <div className={b('col')}>
167
- {tableStatsInfo.map((info, index) => (
168
- <React.Fragment key={index}>
169
- {this.renderItem(info, index === 0 ? 'Table Stats' : undefined)}
170
- </React.Fragment>
171
- ))}
172
184
  </div>
173
185
  </div>
174
186
  );
@@ -176,11 +188,12 @@ class SchemaInfoViewer extends React.Component {
176
188
 
177
189
  render() {
178
190
  const {data} = this.props;
191
+ const entityName = getEntityName(data?.PathDescription);
179
192
 
180
193
  if (data) {
181
194
  return <div className={b()}>{this.renderContent(data)}</div>;
182
195
  } else {
183
- return <div className="error">no schema data</div>;
196
+ return <div className="error">No {entityName} data</div>;
184
197
  }
185
198
  }
186
199
  }
@@ -26,4 +26,12 @@
26
26
  grid-template-columns: minmax(max-content, 280px);
27
27
  }
28
28
  }
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
+ }
29
37
  }
@@ -90,7 +90,7 @@ function Tenant(props: TenantProps) {
90
90
 
91
91
  useEffect(() => {
92
92
  dispatch(disableAutorefresh());
93
- }, [currentSchemaPath, tenantName]);
93
+ }, [currentSchemaPath, tenantName, dispatch]);
94
94
 
95
95
  useEffect(() => {
96
96
  if (tenantName) {
@@ -0,0 +1,8 @@
1
+ import {TPathDescription} from '../../../types/api/schema';
2
+ import {mapPathTypeToEntityName} from './schema';
3
+
4
+ export const getEntityName = (pathDescription?: TPathDescription) => {
5
+ const {PathType, PathSubType} = pathDescription?.Self || {};
6
+
7
+ return mapPathTypeToEntityName(PathType, PathSubType);
8
+ };
@@ -1,5 +1,7 @@
1
1
  import type {NavigationTreeNodeType} from 'ydb-ui-components';
2
+
2
3
  import {EPathSubType, EPathType} from '../../../types/api/schema';
4
+ import {ETenantType} from '../../../types/api/tenant';
3
5
 
4
6
  // this file contains verbose mappings that are typed in a way that ensures
5
7
  // correctness when a new node type or a new path type is added
@@ -41,6 +43,49 @@ export const mapPathTypeToNavigationTreeType = (
41
43
 
42
44
  // ====================
43
45
 
46
+ const pathSubTypeToEntityName: Record<EPathSubType, string | undefined> = {
47
+ [EPathSubType.EPathSubTypeSyncIndexImplTable]: 'Secondary Index Table',
48
+ [EPathSubType.EPathSubTypeAsyncIndexImplTable]: 'Secondary Index Table',
49
+
50
+ [EPathSubType.EPathSubTypeStreamImpl]: undefined,
51
+ [EPathSubType.EPathSubTypeEmpty]: undefined,
52
+ };
53
+
54
+ const pathTypeToEntityName: Record<EPathType, string | undefined> = {
55
+ [EPathType.EPathTypeInvalid]: undefined,
56
+
57
+ [EPathType.EPathTypeSubDomain]: 'Database',
58
+ [EPathType.EPathTypeExtSubDomain]: 'Database',
59
+
60
+ [EPathType.EPathTypeDir]: 'Directory',
61
+ [EPathType.EPathTypeTable]: 'Table',
62
+ [EPathType.EPathTypeTableIndex]: 'Secondary Index',
63
+ [EPathType.EPathTypeColumnStore]: 'Tablestore',
64
+ [EPathType.EPathTypeColumnTable]: 'Columntable',
65
+ [EPathType.EPathTypeCdcStream]: 'Changefeed',
66
+ [EPathType.EPathTypePersQueueGroup]: 'Topic',
67
+ };
68
+
69
+ export const mapPathTypeToEntityName = (
70
+ type?: EPathType,
71
+ subType?: EPathSubType,
72
+ ): string | undefined =>
73
+ (subType && pathSubTypeToEntityName[subType]) || (type && pathTypeToEntityName[type]);
74
+
75
+ // ====================
76
+
77
+ const databaseTypeToDBName: Record<ETenantType, string | undefined> = {
78
+ [ETenantType.UnknownTenantType]: 'Database',
79
+ [ETenantType.Domain]: 'Cluster Root',
80
+ [ETenantType.Dedicated]: 'Dedicated Database',
81
+ [ETenantType.Shared]: 'Shared Database',
82
+ [ETenantType.Serverless]: 'Serverless Database',
83
+ };
84
+
85
+ export const mapDatabaseTypeToDBName = (type?: ETenantType) => type && databaseTypeToDBName[type];
86
+
87
+ // ====================
88
+
44
89
  const pathTypeToIsTable: Record<EPathType, boolean> = {
45
90
  [EPathType.EPathTypeTable]: true,
46
91
  [EPathType.EPathTypeColumnTable]: true,
@@ -10,7 +10,7 @@ import {Loader, TextInput, Button} from '@gravity-ui/uikit';
10
10
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
11
11
  import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
12
12
  import TabletsStatistic from '../../components/TabletsStatistic/TabletsStatistic';
13
- import ProblemFilter, {problemFilterType} from '../../components/ProblemFilter/ProblemFilter';
13
+ import {ProblemFilter} from '../../components/ProblemFilter';
14
14
  import {Illustration} from '../../components/Illustration';
15
15
  import {AutoFetcher} from '../../utils/autofetcher';
16
16
 
@@ -50,7 +50,7 @@ class Tenants extends React.Component {
50
50
  searchQuery: PropTypes.string,
51
51
  handleSearchQuery: PropTypes.func,
52
52
  setHeader: PropTypes.func,
53
- filter: problemFilterType,
53
+ filter: PropTypes.string,
54
54
  changeFilter: PropTypes.func,
55
55
  cluster: PropTypes.object,
56
56
  singleClusterMode: PropTypes.bool,
@@ -45,6 +45,9 @@ interface Window {
45
45
  getHealthcheckInfo: (
46
46
  database: string,
47
47
  ) => Promise<import('../types/api/healthcheck').HealthCheckAPIResponse>;
48
+ getTenantInfo: (params: {
49
+ path: string;
50
+ }) => Promise<import('../types/api/tenant').TTenantInfo>;
48
51
  [method: string]: Function;
49
52
  };
50
53
  }
@@ -1,4 +1,4 @@
1
- import AxiosWrapper from '@yandex-cloud/axios-wrapper';
1
+ import AxiosWrapper from '@gravity-ui/axios-wrapper';
2
2
 
3
3
  import {backend as BACKEND} from '../store';
4
4
  import {StorageTypes} from '../store/reducers/storage';
@@ -1,8 +1,12 @@
1
- import {createRequestActionTypes, createApiRequest} from '../utils';
1
+ import type {Reducer} from 'redux';
2
+
2
3
  import '../../services/api';
3
4
  import {NodesUptimeFilterValues} from '../../utils/nodes';
5
+ import {INodesAction, INodesRootStateSlice, INodesState} from '../../types/store/nodes';
6
+
7
+ import {createRequestActionTypes, createApiRequest} from '../utils';
4
8
 
5
- const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
9
+ export const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
6
10
 
7
11
  const CLEAR_NODES = 'nodes/CLEAR_NODES';
8
12
  const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
@@ -14,13 +18,12 @@ const initialState = {
14
18
  nodesUptimeFilter: NodesUptimeFilterValues.All,
15
19
  };
16
20
 
17
- const nodes = (state = initialState, action) => {
21
+ const nodes: Reducer<INodesState, INodesAction> = (state = initialState, action) => {
18
22
  switch (action.type) {
19
23
  case FETCH_NODES.REQUEST: {
20
24
  return {
21
25
  ...state,
22
26
  loading: true,
23
- requestTime: new Date().getTime(),
24
27
  };
25
28
  }
26
29
  case FETCH_NODES.SUCCESS: {
@@ -45,13 +48,15 @@ const nodes = (state = initialState, action) => {
45
48
  loading: true,
46
49
  data: undefined,
47
50
  wasLoaded: false,
48
- requestTime: new Date().getTime(),
49
51
  error: undefined,
50
52
  };
51
53
  }
52
54
 
53
55
  case SET_NODES_UPTIME_FILTER: {
54
- return {...state, nodesUptimeFilter: action.data};
56
+ return {
57
+ ...state,
58
+ nodesUptimeFilter: action.data,
59
+ };
55
60
  }
56
61
  case SET_DATA_WAS_NOT_LOADED: {
57
62
  return {
@@ -64,26 +69,27 @@ const nodes = (state = initialState, action) => {
64
69
  }
65
70
  };
66
71
 
67
- export function getNodes(path) {
72
+ export function getNodes(path: string) {
68
73
  return createApiRequest({
69
74
  request: window.api.getNodes(path),
70
75
  actions: FETCH_NODES,
71
76
  });
72
77
  }
73
78
 
74
- export const clearNodes = () => ({type: CLEAR_NODES});
79
+ export const clearNodes = () => ({type: CLEAR_NODES} as const);
75
80
 
76
- export const setNodesUptimeFilter = (value) => ({
77
- type: SET_NODES_UPTIME_FILTER,
78
- data: value,
79
- });
81
+ export const setNodesUptimeFilter = (value: NodesUptimeFilterValues) =>
82
+ ({
83
+ type: SET_NODES_UPTIME_FILTER,
84
+ data: value,
85
+ } as const);
80
86
 
81
87
  export const setDataWasNotLoaded = () => {
82
88
  return {
83
89
  type: SET_DATA_WAS_NOT_LOADED,
84
- };
90
+ } as const;
85
91
  };
86
92
 
87
- export const getNodesUptimeFilter = (state) => state.nodes.nodesUptimeFilter;
93
+ export const getNodesUptimeFilter = (state: INodesRootStateSlice) => state.nodes.nodesUptimeFilter;
88
94
 
89
95
  export default nodes;