ydb-embedded-ui 2.5.0 → 3.0.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.
- package/CHANGELOG.md +40 -0
- package/dist/components/InfoViewer/InfoViewer.scss +3 -3
- package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +23 -9
- package/dist/containers/Storage/Pdisk/Pdisk.tsx +3 -9
- package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +1 -1
- package/dist/containers/Storage/Storage.js +11 -1
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +39 -32
- package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +21 -13
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +22 -6
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +40 -9
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +15 -9
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +13 -5
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +17 -4
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +50 -16
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +16 -2
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +1 -0
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +2 -2
- package/dist/containers/Tenant/utils/schema.ts +84 -0
- package/dist/services/api.d.ts +17 -11
- package/dist/store/reducers/describe.ts +56 -14
- package/dist/store/reducers/healthcheckInfo.ts +23 -8
- package/dist/store/reducers/network.js +22 -1
- package/dist/store/reducers/nodes.js +13 -0
- package/dist/store/reducers/schema.ts +84 -11
- package/dist/store/reducers/storage.js +13 -0
- package/dist/types/api/enums.ts +10 -0
- package/dist/types/api/nodes.ts +96 -0
- package/dist/types/api/pdisk.ts +48 -0
- package/dist/types/api/schema.ts +148 -9
- package/dist/types/api/storage.ts +3 -173
- package/dist/types/api/tablet.ts +97 -0
- package/dist/types/api/vdisk.ts +120 -0
- package/dist/types/store/describe.ts +8 -2
- package/dist/types/store/healthcheck.ts +12 -0
- package/dist/types/store/schema.ts +7 -1
- package/dist/utils/pdisk.ts +1 -1
- package/dist/utils/storage.ts +1 -1
- package/package.json +3 -2
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
getHealthcheckInfo,
|
11
11
|
selectIssuesTreeById,
|
12
12
|
selectIssuesTreesRoots,
|
13
|
+
setDataWasNotLoaded,
|
13
14
|
} from '../../../../store/reducers/healthcheckInfo';
|
14
15
|
|
15
16
|
import {Details} from './Details';
|
@@ -43,14 +44,21 @@ export const Healthcheck = (props: HealthcheckProps) => {
|
|
43
44
|
|
44
45
|
const {autorefresh} = useTypedSelector((state) => state.schema);
|
45
46
|
|
46
|
-
const fetchHealthcheck = useCallback(
|
47
|
-
|
48
|
-
|
47
|
+
const fetchHealthcheck = useCallback(
|
48
|
+
(isBackground = true) => {
|
49
|
+
if (!isBackground) {
|
50
|
+
dispatch(setDataWasNotLoaded());
|
51
|
+
}
|
52
|
+
|
53
|
+
dispatch(getHealthcheckInfo(tenant));
|
54
|
+
},
|
55
|
+
[dispatch, tenant],
|
56
|
+
);
|
49
57
|
|
50
58
|
useAutofetcher(
|
51
|
-
() => {
|
59
|
+
(isBackground) => {
|
52
60
|
if (fetchData) {
|
53
|
-
fetchHealthcheck();
|
61
|
+
fetchHealthcheck(isBackground);
|
54
62
|
}
|
55
63
|
},
|
56
64
|
[fetchData, fetchHealthcheck],
|
@@ -12,7 +12,7 @@ import Icon from '../../../../components/Icon/Icon';
|
|
12
12
|
import ProblemFilter, {problemFilterType} from '../../../../components/ProblemFilter/ProblemFilter';
|
13
13
|
import {Illustration} from '../../../../components/Illustration';
|
14
14
|
|
15
|
-
import {getNetworkInfo} from '../../../../store/reducers/network';
|
15
|
+
import {getNetworkInfo, setDataWasNotLoaded} from '../../../../store/reducers/network';
|
16
16
|
import {hideTooltip, showTooltip} from '../../../../store/reducers/tooltip';
|
17
17
|
import {ALL, PROBLEMS} from '../../../../utils/constants';
|
18
18
|
import {changeFilter} from '../../../../store/reducers/settings';
|
@@ -26,6 +26,7 @@ const b = cn('network');
|
|
26
26
|
class Network extends React.Component {
|
27
27
|
static propTypes = {
|
28
28
|
getNetworkInfo: PropTypes.func,
|
29
|
+
setDataWasNotLoaded: PropTypes.func,
|
29
30
|
netWorkInfo: PropTypes.object,
|
30
31
|
hideTooltip: PropTypes.func,
|
31
32
|
showTooltip: PropTypes.func,
|
@@ -75,16 +76,27 @@ class Network extends React.Component {
|
|
75
76
|
}
|
76
77
|
|
77
78
|
componentDidUpdate(prevProps) {
|
78
|
-
const {autorefresh, path} = this.props;
|
79
|
+
const {autorefresh, path, setDataWasNotLoaded, getNetworkInfo} = this.props;
|
79
80
|
|
80
|
-
|
81
|
-
|
81
|
+
const restartAutorefresh = () => {
|
82
|
+
this.autofetcher.stop();
|
82
83
|
this.autofetcher.start();
|
83
84
|
this.autofetcher.fetch(() => getNetworkInfo(path));
|
85
|
+
};
|
86
|
+
|
87
|
+
if (autorefresh && !prevProps.autorefresh) {
|
88
|
+
getNetworkInfo(path);
|
89
|
+
restartAutorefresh();
|
84
90
|
}
|
85
91
|
if (!autorefresh && prevProps.autorefresh) {
|
86
92
|
this.autofetcher.stop();
|
87
93
|
}
|
94
|
+
|
95
|
+
if (path !== prevProps.path) {
|
96
|
+
setDataWasNotLoaded();
|
97
|
+
getNetworkInfo(path);
|
98
|
+
restartAutorefresh();
|
99
|
+
}
|
88
100
|
}
|
89
101
|
|
90
102
|
componentWillUnmount() {
|
@@ -364,6 +376,7 @@ const mapDispatchToProps = {
|
|
364
376
|
hideTooltip,
|
365
377
|
showTooltip,
|
366
378
|
changeFilter,
|
379
|
+
setDataWasNotLoaded,
|
367
380
|
};
|
368
381
|
|
369
382
|
export default connect(mapStateToProps, mapDispatchToProps)(Network);
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import {ReactNode, useMemo} from 'react';
|
2
|
-
import {useDispatch, useSelector} from 'react-redux';
|
1
|
+
import {ReactNode, useCallback, useMemo} from 'react';
|
2
|
+
import {shallowEqual, useDispatch, useSelector} from 'react-redux';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
|
5
5
|
import {Loader} from '@gravity-ui/uikit';
|
@@ -13,15 +13,24 @@ import {
|
|
13
13
|
} from '../../../../components/InfoViewer/schemaInfo';
|
14
14
|
|
15
15
|
import {EPathType, TColumnTableDescription} from '../../../../types/api/schema';
|
16
|
-
import {
|
16
|
+
import {
|
17
|
+
isEntityWithMergedImplementation,
|
18
|
+
isColumnEntityType,
|
19
|
+
isTableType,
|
20
|
+
} from '../../utils/schema';
|
17
21
|
//@ts-ignore
|
18
|
-
import {
|
22
|
+
import {
|
23
|
+
getSchema,
|
24
|
+
getSchemaBatched,
|
25
|
+
resetLoadingState,
|
26
|
+
selectSchemaMergedChildrenPaths,
|
27
|
+
} from '../../../../store/reducers/schema';
|
19
28
|
//@ts-ignore
|
20
29
|
import {
|
21
30
|
getOlapStats,
|
22
31
|
resetLoadingState as resetOlapLoadingState,
|
23
32
|
} from '../../../../store/reducers/olapStats';
|
24
|
-
import {useAutofetcher} from '../../../../utils/hooks';
|
33
|
+
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
25
34
|
|
26
35
|
import './Overview.scss';
|
27
36
|
|
@@ -60,9 +69,7 @@ interface OverviewProps {
|
|
60
69
|
|
61
70
|
const b = cn('kv-tenant-overview');
|
62
71
|
|
63
|
-
function Overview(
|
64
|
-
const {tenantName, type} = props;
|
65
|
-
|
72
|
+
function Overview({type, tenantName, className}: OverviewProps) {
|
66
73
|
const dispatch = useDispatch();
|
67
74
|
|
68
75
|
const {
|
@@ -78,14 +85,31 @@ function Overview(props: OverviewProps) {
|
|
78
85
|
|
79
86
|
const loading = schemaLoading || olapStatsLoading;
|
80
87
|
|
81
|
-
|
82
|
-
|
88
|
+
const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);
|
89
|
+
|
90
|
+
// There is a circular dependency here. Fetch data depends on children paths
|
91
|
+
// When data in store updated on fetch request,
|
92
|
+
// new object is set there, so source children array is updated
|
93
|
+
// This updates selector, the selector returns a new array, and data is fetched again
|
94
|
+
// To prevent it, shallowEqual, which compares array content, was added
|
95
|
+
const mergedChildrenPaths = useTypedSelector(
|
96
|
+
(state) => selectSchemaMergedChildrenPaths(state, currentSchemaPath, type),
|
97
|
+
shallowEqual,
|
98
|
+
);
|
99
|
+
|
100
|
+
const fetchData = useCallback(
|
101
|
+
(isBackground: boolean) => {
|
83
102
|
if (!isBackground) {
|
84
103
|
dispatch(resetLoadingState());
|
85
104
|
}
|
86
105
|
|
87
106
|
const schemaPath = currentSchemaPath || tenantName;
|
88
|
-
|
107
|
+
|
108
|
+
if (!isEntityWithMergedImpl) {
|
109
|
+
dispatch(getSchema({path: schemaPath}));
|
110
|
+
} else if (mergedChildrenPaths) {
|
111
|
+
dispatch(getSchemaBatched([schemaPath, ...mergedChildrenPaths]));
|
112
|
+
}
|
89
113
|
|
90
114
|
if (isTableType(type) && isColumnEntityType(type)) {
|
91
115
|
if (!isBackground) {
|
@@ -94,10 +118,18 @@ function Overview(props: OverviewProps) {
|
|
94
118
|
dispatch(getOlapStats({path: schemaPath}));
|
95
119
|
}
|
96
120
|
},
|
97
|
-
[
|
98
|
-
|
121
|
+
[
|
122
|
+
tenantName,
|
123
|
+
currentSchemaPath,
|
124
|
+
type,
|
125
|
+
isEntityWithMergedImpl,
|
126
|
+
mergedChildrenPaths,
|
127
|
+
dispatch,
|
128
|
+
],
|
99
129
|
);
|
100
130
|
|
131
|
+
useAutofetcher(fetchData, [fetchData], autorefresh);
|
132
|
+
|
101
133
|
const tableSchema =
|
102
134
|
currentItem?.PathDescription?.Table || currentItem?.PathDescription?.ColumnTableDescription;
|
103
135
|
|
@@ -128,7 +160,9 @@ function Overview(props: OverviewProps) {
|
|
128
160
|
[EPathType.EPathTypeExtSubDomain]: undefined,
|
129
161
|
[EPathType.EPathTypeColumnStore]: undefined,
|
130
162
|
[EPathType.EPathTypeColumnTable]: undefined,
|
131
|
-
[EPathType.EPathTypeCdcStream]: () =>
|
163
|
+
[EPathType.EPathTypeCdcStream]: () => (
|
164
|
+
<CDCStreamInfo data={schemaData} childrenPaths={mergedChildrenPaths} />
|
165
|
+
),
|
132
166
|
[EPathType.EPathTypePersQueueGroup]: () => <PersQueueGroupInfo data={schemaData} />,
|
133
167
|
};
|
134
168
|
|
@@ -139,10 +173,10 @@ function Overview(props: OverviewProps) {
|
|
139
173
|
);
|
140
174
|
};
|
141
175
|
|
142
|
-
return loading && !wasLoaded ? (
|
176
|
+
return (loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths) ? (
|
143
177
|
renderLoader()
|
144
178
|
) : (
|
145
|
-
<div className={
|
179
|
+
<div className={className}>{renderContent()}</div>
|
146
180
|
);
|
147
181
|
}
|
148
182
|
|
@@ -53,6 +53,7 @@ class TenantOverview extends React.Component {
|
|
53
53
|
|
54
54
|
componentDidMount() {
|
55
55
|
const {tenantName, autorefresh, getTenantInfo} = this.props;
|
56
|
+
getTenantInfo({path: tenantName});
|
56
57
|
this.autofetcher = new AutoFetcher();
|
57
58
|
if (autorefresh) {
|
58
59
|
this.autofetcher.start();
|
@@ -62,12 +63,25 @@ class TenantOverview extends React.Component {
|
|
62
63
|
|
63
64
|
componentDidUpdate(prevProps) {
|
64
65
|
const {autorefresh, tenantName, getTenantInfo} = this.props;
|
65
|
-
|
66
|
-
|
66
|
+
|
67
|
+
const restartAutorefresh = () => {
|
67
68
|
this.autofetcher.stop();
|
68
69
|
this.autofetcher.start();
|
69
70
|
this.autofetcher.fetch(() => getTenantInfo({path: tenantName}));
|
71
|
+
};
|
72
|
+
|
73
|
+
if (prevProps.tenantName !== this.props.tenantName) {
|
74
|
+
getTenantInfo({path: tenantName});
|
75
|
+
if (autorefresh) {
|
76
|
+
restartAutorefresh();
|
77
|
+
}
|
70
78
|
}
|
79
|
+
|
80
|
+
if (autorefresh && !prevProps.autorefresh) {
|
81
|
+
getTenantInfo({path: tenantName});
|
82
|
+
restartAutorefresh();
|
83
|
+
}
|
84
|
+
|
71
85
|
if (!autorefresh && prevProps.autorefresh) {
|
72
86
|
this.autofetcher.stop();
|
73
87
|
}
|
@@ -6,7 +6,7 @@ import {NavigationTree} from 'ydb-ui-components';
|
|
6
6
|
import {setCurrentSchemaPath, preloadSchemas} from '../../../../store/reducers/schema';
|
7
7
|
import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
|
8
8
|
|
9
|
-
import {mapPathTypeToNavigationTreeType} from '../../utils/schema';
|
9
|
+
import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema';
|
10
10
|
import {getActions} from '../../utils/schemaActions';
|
11
11
|
|
12
12
|
interface SchemaTreeProps {
|
@@ -42,7 +42,7 @@ export function SchemaTree(props: SchemaTreeProps) {
|
|
42
42
|
type: mapPathTypeToNavigationTreeType(PathType, PathSubType),
|
43
43
|
// FIXME: should only be explicitly set to true for tables with indexes
|
44
44
|
// at the moment of writing there is no property to determine this, fix later
|
45
|
-
expandable:
|
45
|
+
expandable: !isChildlessPathType(PathType, PathSubType),
|
46
46
|
};
|
47
47
|
});
|
48
48
|
|
@@ -88,3 +88,87 @@ const pathTypeToIsColumn: Record<EPathType, boolean> = {
|
|
88
88
|
};
|
89
89
|
|
90
90
|
export const isColumnEntityType = (type?: EPathType) => (type && pathTypeToIsColumn[type]) ?? false;
|
91
|
+
|
92
|
+
// ====================
|
93
|
+
|
94
|
+
const pathTypeToIsDatabase: Record<EPathType, boolean> = {
|
95
|
+
[EPathType.EPathTypeSubDomain]: true,
|
96
|
+
[EPathType.EPathTypeExtSubDomain]: true,
|
97
|
+
|
98
|
+
[EPathType.EPathTypeInvalid]: false,
|
99
|
+
[EPathType.EPathTypeDir]: false,
|
100
|
+
[EPathType.EPathTypeColumnStore]: false,
|
101
|
+
[EPathType.EPathTypeColumnTable]: false,
|
102
|
+
[EPathType.EPathTypeTable]: false,
|
103
|
+
[EPathType.EPathTypeTableIndex]: false,
|
104
|
+
[EPathType.EPathTypeCdcStream]: false,
|
105
|
+
[EPathType.EPathTypePersQueueGroup]: false,
|
106
|
+
};
|
107
|
+
|
108
|
+
export const isDatabaseEntityType = (type?: EPathType) =>
|
109
|
+
(type && pathTypeToIsDatabase[type]) ?? false;
|
110
|
+
|
111
|
+
// ====================
|
112
|
+
|
113
|
+
const pathTypeToIsCdcStream: Record<EPathType, boolean> = {
|
114
|
+
[EPathType.EPathTypeCdcStream]: true,
|
115
|
+
|
116
|
+
[EPathType.EPathTypeInvalid]: false,
|
117
|
+
[EPathType.EPathTypeColumnStore]: false,
|
118
|
+
[EPathType.EPathTypeColumnTable]: false,
|
119
|
+
[EPathType.EPathTypeDir]: false,
|
120
|
+
[EPathType.EPathTypeTable]: false,
|
121
|
+
[EPathType.EPathTypeSubDomain]: false,
|
122
|
+
[EPathType.EPathTypeTableIndex]: false,
|
123
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
124
|
+
[EPathType.EPathTypePersQueueGroup]: false,
|
125
|
+
};
|
126
|
+
|
127
|
+
export const isCdcStreamEntityType = (type?: EPathType) =>
|
128
|
+
(type && pathTypeToIsCdcStream[type]) ?? false;
|
129
|
+
|
130
|
+
// ====================
|
131
|
+
|
132
|
+
const pathTypeToEntityWithMergedImplementation: Record<EPathType, boolean> = {
|
133
|
+
[EPathType.EPathTypeCdcStream]: true,
|
134
|
+
|
135
|
+
[EPathType.EPathTypePersQueueGroup]: false,
|
136
|
+
[EPathType.EPathTypeInvalid]: false,
|
137
|
+
[EPathType.EPathTypeColumnStore]: false,
|
138
|
+
[EPathType.EPathTypeColumnTable]: false,
|
139
|
+
[EPathType.EPathTypeDir]: false,
|
140
|
+
[EPathType.EPathTypeTable]: false,
|
141
|
+
[EPathType.EPathTypeSubDomain]: false,
|
142
|
+
[EPathType.EPathTypeTableIndex]: false,
|
143
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
144
|
+
};
|
145
|
+
|
146
|
+
export const isEntityWithMergedImplementation = (type?: EPathType) =>
|
147
|
+
(type && pathTypeToEntityWithMergedImplementation[type]) ?? false;
|
148
|
+
|
149
|
+
// ====================
|
150
|
+
|
151
|
+
const pathSubTypeToChildless: Record<EPathSubType, boolean> = {
|
152
|
+
[EPathSubType.EPathSubTypeSyncIndexImplTable]: true,
|
153
|
+
[EPathSubType.EPathSubTypeAsyncIndexImplTable]: true,
|
154
|
+
|
155
|
+
[EPathSubType.EPathSubTypeStreamImpl]: false,
|
156
|
+
[EPathSubType.EPathSubTypeEmpty]: false,
|
157
|
+
};
|
158
|
+
|
159
|
+
const pathTypeToChildless: Record<EPathType, boolean> = {
|
160
|
+
[EPathType.EPathTypeCdcStream]: true,
|
161
|
+
[EPathType.EPathTypePersQueueGroup]: true,
|
162
|
+
|
163
|
+
[EPathType.EPathTypeInvalid]: false,
|
164
|
+
[EPathType.EPathTypeColumnStore]: false,
|
165
|
+
[EPathType.EPathTypeColumnTable]: false,
|
166
|
+
[EPathType.EPathTypeDir]: false,
|
167
|
+
[EPathType.EPathTypeTable]: false,
|
168
|
+
[EPathType.EPathTypeSubDomain]: false,
|
169
|
+
[EPathType.EPathTypeTableIndex]: false,
|
170
|
+
[EPathType.EPathTypeExtSubDomain]: false,
|
171
|
+
};
|
172
|
+
|
173
|
+
export const isChildlessPathType = (type?: EPathType, subType?: EPathSubType) =>
|
174
|
+
((subType && pathSubTypeToChildless[subType]) || (type && pathTypeToChildless[type])) ?? false;
|
package/dist/services/api.d.ts
CHANGED
@@ -8,25 +8,29 @@ interface Window {
|
|
8
8
|
params: {path: string},
|
9
9
|
axiosOptions?: AxiosOptions,
|
10
10
|
) => Promise<import('../types/api/schema').TEvDescribeSchemeResult>;
|
11
|
+
getDescribe: (
|
12
|
+
params: {path: string},
|
13
|
+
axiosOptions?: AxiosOptions,
|
14
|
+
) => Promise<import('../types/api/schema').TEvDescribeSchemeResult>;
|
11
15
|
getStorageInfo: (
|
12
16
|
params: {
|
13
|
-
tenant: string
|
14
|
-
filter: string
|
15
|
-
nodeId: string
|
16
|
-
type: 'Groups' | 'Nodes'
|
17
|
+
tenant: string;
|
18
|
+
filter: string;
|
19
|
+
nodeId: string;
|
20
|
+
type: 'Groups' | 'Nodes';
|
17
21
|
},
|
18
22
|
axiosOptions?: AxiosOptions,
|
19
23
|
) => Promise<import('../types/api/storage').TStorageInfo>;
|
20
24
|
sendQuery: <
|
21
25
|
Action extends import('../types/api/query').Actions,
|
22
|
-
Schema extends import('../types/api/query').Schemas = undefined
|
26
|
+
Schema extends import('../types/api/query').Schemas = undefined,
|
23
27
|
>(
|
24
28
|
params: {
|
25
|
-
query?: string
|
26
|
-
database?: string
|
27
|
-
action?: Action
|
28
|
-
stats?: string
|
29
|
-
schema?: Schema
|
29
|
+
query?: string;
|
30
|
+
database?: string;
|
31
|
+
action?: Action;
|
32
|
+
stats?: string;
|
33
|
+
schema?: Schema;
|
30
34
|
},
|
31
35
|
axiosOptions?: AxiosOptions,
|
32
36
|
) => Promise<import('../types/api/query').QueryAPIResponse<Action, Schema>>;
|
@@ -38,7 +42,9 @@ interface Window {
|
|
38
42
|
query: string,
|
39
43
|
database: string,
|
40
44
|
) => Promise<import('../types/api/query').QueryAPIExplainResponse<'explain-ast'>>;
|
41
|
-
getHealthcheckInfo: (
|
45
|
+
getHealthcheckInfo: (
|
46
|
+
database: string,
|
47
|
+
) => Promise<import('../types/api/healthcheck').HealthCheckAPIResponse>;
|
42
48
|
[method: string]: Function;
|
43
49
|
};
|
44
50
|
}
|
@@ -3,7 +3,13 @@ import {Reducer} from 'redux';
|
|
3
3
|
|
4
4
|
import '../../services/api';
|
5
5
|
import {IConsumer} from '../../types/api/consumers';
|
6
|
-
import {
|
6
|
+
import {
|
7
|
+
IDescribeRootStateSlice,
|
8
|
+
IDescribeState,
|
9
|
+
IDescribeAction,
|
10
|
+
IDescribeHandledResponse,
|
11
|
+
IDescribeData,
|
12
|
+
} from '../../types/store/describe';
|
7
13
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
8
14
|
|
9
15
|
export const FETCH_DESCRIBE = createRequestActionTypes('describe', 'FETCH_DESCRIBE');
|
@@ -27,16 +33,8 @@ const describe: Reducer<IDescribeState, IDescribeAction> = (state = initialState
|
|
27
33
|
};
|
28
34
|
}
|
29
35
|
case FETCH_DESCRIBE.SUCCESS: {
|
30
|
-
const
|
31
|
-
|
32
|
-
const isCurrentDescribePath = data.Path === state.currentDescribePath;
|
33
|
-
|
34
|
-
let newData = state.data;
|
35
|
-
|
36
|
-
if (data.Path) {
|
37
|
-
newData = JSON.parse(JSON.stringify(state.data));
|
38
|
-
newData[data.Path] = data;
|
39
|
-
}
|
36
|
+
const isCurrentDescribePath = action.data.path === state.currentDescribePath;
|
37
|
+
const newData = {...state.data, ...action.data.data};
|
40
38
|
|
41
39
|
if (!isCurrentDescribePath) {
|
42
40
|
return {
|
@@ -48,7 +46,7 @@ const describe: Reducer<IDescribeState, IDescribeAction> = (state = initialState
|
|
48
46
|
return {
|
49
47
|
...state,
|
50
48
|
data: newData,
|
51
|
-
currentDescribe: data,
|
49
|
+
currentDescribe: action.data.currentDescribe,
|
52
50
|
loading: false,
|
53
51
|
wasLoaded: true,
|
54
52
|
error: undefined,
|
@@ -97,7 +95,7 @@ export const setDataWasNotLoaded = () => {
|
|
97
95
|
};
|
98
96
|
|
99
97
|
// Consumers selectors
|
100
|
-
const selectConsumersNames = (state: IDescribeRootStateSlice, path
|
98
|
+
const selectConsumersNames = (state: IDescribeRootStateSlice, path?: string) =>
|
101
99
|
path
|
102
100
|
? state.describe.data[path]?.PathDescription?.PersQueueGroup?.PQTabletConfig?.ReadRules
|
103
101
|
: undefined;
|
@@ -106,9 +104,53 @@ export const selectConsumers: Selector<IDescribeRootStateSlice, IConsumer[], [st
|
|
106
104
|
createSelector(selectConsumersNames, (names = []) => names.map((name) => ({name})));
|
107
105
|
|
108
106
|
export function getDescribe({path}: {path: string}) {
|
107
|
+
const request = window.api.getDescribe({path});
|
108
|
+
return createApiRequest({
|
109
|
+
request,
|
110
|
+
actions: FETCH_DESCRIBE,
|
111
|
+
dataHandler: (data): IDescribeHandledResponse => {
|
112
|
+
const dataPath = data.Path;
|
113
|
+
const currentDescribe: IDescribeData = {};
|
114
|
+
const newData: IDescribeData = {};
|
115
|
+
|
116
|
+
if (dataPath) {
|
117
|
+
currentDescribe[dataPath] = data;
|
118
|
+
newData[dataPath] = data;
|
119
|
+
}
|
120
|
+
|
121
|
+
return {
|
122
|
+
path: dataPath,
|
123
|
+
currentDescribe,
|
124
|
+
data: newData,
|
125
|
+
};
|
126
|
+
},
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
export function getDescribeBatched(paths: string[]) {
|
131
|
+
const requestsArray = paths.map((p) => window.api.getDescribe({path: p}));
|
132
|
+
|
133
|
+
const request = Promise.all(requestsArray);
|
109
134
|
return createApiRequest({
|
110
|
-
request
|
135
|
+
request,
|
111
136
|
actions: FETCH_DESCRIBE,
|
137
|
+
dataHandler: (data): IDescribeHandledResponse => {
|
138
|
+
const currentDescribe: IDescribeData = {};
|
139
|
+
const newData: IDescribeData = {};
|
140
|
+
|
141
|
+
data.forEach((dataItem) => {
|
142
|
+
if (dataItem.Path) {
|
143
|
+
newData[dataItem.Path] = dataItem;
|
144
|
+
currentDescribe[dataItem.Path] = dataItem;
|
145
|
+
}
|
146
|
+
});
|
147
|
+
|
148
|
+
return {
|
149
|
+
path: data[0].Path,
|
150
|
+
currentDescribe,
|
151
|
+
data: newData,
|
152
|
+
};
|
153
|
+
},
|
112
154
|
});
|
113
155
|
}
|
114
156
|
|
@@ -9,21 +9,23 @@ import {
|
|
9
9
|
IHealthcheckInfoState,
|
10
10
|
IHealthcheckInfoRootStateSlice,
|
11
11
|
IIssuesTree,
|
12
|
+
IHealthCheckInfoAction,
|
12
13
|
} from '../../types/store/healthcheck';
|
13
|
-
import {
|
14
|
-
import {IResponseError} from '../../types/api/error';
|
14
|
+
import {IssueLog, StatusFlag} from '../../types/api/healthcheck';
|
15
15
|
|
16
16
|
import '../../services/api';
|
17
|
-
import {createRequestActionTypes, createApiRequest
|
17
|
+
import {createRequestActionTypes, createApiRequest} from '../utils';
|
18
18
|
|
19
|
-
const FETCH_HEALTHCHECK = createRequestActionTypes('cluster', 'FETCH_HEALTHCHECK');
|
19
|
+
export const FETCH_HEALTHCHECK = createRequestActionTypes('cluster', 'FETCH_HEALTHCHECK');
|
20
|
+
|
21
|
+
const SET_DATA_WAS_NOT_LOADED = 'healthcheckInfo/SET_DATA_WAS_NOT_LOADED';
|
20
22
|
|
21
23
|
const initialState = {loading: false, wasLoaded: false};
|
22
24
|
|
23
|
-
const healthcheckInfo: Reducer<
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
const healthcheckInfo: Reducer<IHealthcheckInfoState, IHealthCheckInfoAction> = function (
|
26
|
+
state = initialState,
|
27
|
+
action,
|
28
|
+
) {
|
27
29
|
switch (action.type) {
|
28
30
|
case FETCH_HEALTHCHECK.REQUEST: {
|
29
31
|
return {
|
@@ -49,6 +51,13 @@ const healthcheckInfo: Reducer<
|
|
49
51
|
loading: false,
|
50
52
|
};
|
51
53
|
}
|
54
|
+
|
55
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
56
|
+
return {
|
57
|
+
...state,
|
58
|
+
wasLoaded: false,
|
59
|
+
};
|
60
|
+
}
|
52
61
|
default:
|
53
62
|
return state;
|
54
63
|
}
|
@@ -127,4 +136,10 @@ export function getHealthcheckInfo(database: string) {
|
|
127
136
|
});
|
128
137
|
}
|
129
138
|
|
139
|
+
export const setDataWasNotLoaded = () => {
|
140
|
+
return {
|
141
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
142
|
+
} as const;
|
143
|
+
};
|
144
|
+
|
130
145
|
export default healthcheckInfo;
|
@@ -6,7 +6,15 @@ const FETCH_ALL_NODES_NETWORK = createRequestActionTypes(
|
|
6
6
|
'FETCH_ALL_NODES_NETWORK',
|
7
7
|
);
|
8
8
|
|
9
|
-
const
|
9
|
+
const SET_DATA_WAS_NOT_LOADED = 'network/SET_DATA_WAS_NOT_LOADED';
|
10
|
+
|
11
|
+
const initialState = {
|
12
|
+
data: {},
|
13
|
+
loading: false,
|
14
|
+
wasLoaded: false,
|
15
|
+
};
|
16
|
+
|
17
|
+
const network = (state = initialState, action) => {
|
10
18
|
switch (action.type) {
|
11
19
|
case FETCH_ALL_NODES_NETWORK.REQUEST: {
|
12
20
|
return {
|
@@ -30,11 +38,24 @@ const network = (state = {data: {}, loading: true, wasLoaded: false}, action) =>
|
|
30
38
|
loading: false,
|
31
39
|
};
|
32
40
|
}
|
41
|
+
|
42
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
43
|
+
return {
|
44
|
+
...state,
|
45
|
+
wasLoaded: false,
|
46
|
+
};
|
47
|
+
}
|
33
48
|
default:
|
34
49
|
return state;
|
35
50
|
}
|
36
51
|
};
|
37
52
|
|
53
|
+
export const setDataWasNotLoaded = () => {
|
54
|
+
return {
|
55
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
56
|
+
};
|
57
|
+
};
|
58
|
+
|
38
59
|
export const getNetworkInfo = (tenant) => {
|
39
60
|
return createApiRequest({
|
40
61
|
request: window.api.getNetwork(tenant),
|
@@ -6,6 +6,7 @@ const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
|
|
6
6
|
|
7
7
|
const CLEAR_NODES = 'nodes/CLEAR_NODES';
|
8
8
|
const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
|
9
|
+
const SET_DATA_WAS_NOT_LOADED = 'nodes/SET_DATA_WAS_NOT_LOADED';
|
9
10
|
|
10
11
|
const initialState = {
|
11
12
|
loading: true,
|
@@ -52,6 +53,12 @@ const nodes = (state = initialState, action) => {
|
|
52
53
|
case SET_NODES_UPTIME_FILTER: {
|
53
54
|
return {...state, nodesUptimeFilter: action.data};
|
54
55
|
}
|
56
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
57
|
+
return {
|
58
|
+
...state,
|
59
|
+
wasLoaded: false,
|
60
|
+
};
|
61
|
+
}
|
55
62
|
default:
|
56
63
|
return state;
|
57
64
|
}
|
@@ -71,6 +78,12 @@ export const setNodesUptimeFilter = (value) => ({
|
|
71
78
|
data: value,
|
72
79
|
});
|
73
80
|
|
81
|
+
export const setDataWasNotLoaded = () => {
|
82
|
+
return {
|
83
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
84
|
+
};
|
85
|
+
};
|
86
|
+
|
74
87
|
export const getNodesUptimeFilter = (state) => state.nodes.nodesUptimeFilter;
|
75
88
|
|
76
89
|
export default nodes;
|