ydb-embedded-ui 4.10.1 → 4.11.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 +17 -0
- package/dist/components/QueryResultTable/Cell/Cell.tsx +8 -8
- package/dist/components/QueryResultTable/i18n/en.json +1 -1
- package/dist/components/QueryResultTable/i18n/ru.json +1 -1
- package/dist/components/ShortyString/ShortyString.tsx +3 -6
- package/dist/components/ShortyString/i18n/en.json +8 -8
- package/dist/components/ShortyString/i18n/ru.json +8 -8
- package/dist/components/SpeedMultiMeter/i18n/index.ts +0 -2
- package/dist/components/Stack/Stack.tsx +16 -16
- package/dist/components/TableSkeleton/TableSkeleton.tsx +3 -3
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +7 -3
- package/dist/containers/Header/Header.tsx +2 -2
- package/dist/containers/Header/breadcrumbs.ts +2 -1
- package/dist/containers/Heatmap/Heatmap.tsx +4 -3
- package/dist/containers/Node/NodeStructure/PDiskTitleBadge.tsx +2 -8
- package/dist/containers/Nodes/Nodes.tsx +1 -1
- package/dist/containers/Storage/EmptyFilter/i18n/en.json +2 -2
- package/dist/containers/Storage/EmptyFilter/i18n/ru.json +2 -2
- package/dist/containers/Storage/StorageGroups/i18n/en.json +5 -5
- package/dist/containers/Storage/StorageGroups/i18n/ru.json +5 -5
- package/dist/containers/Storage/UsageFilter/i18n/en.json +3 -8
- package/dist/containers/Storage/UsageFilter/i18n/ru.json +3 -8
- package/dist/containers/Tablet/Tablet.tsx +2 -2
- package/dist/containers/Tenant/Acl/Acl.scss +1 -9
- package/dist/containers/Tenant/Acl/Acl.tsx +137 -0
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +6 -0
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +2 -0
- package/dist/containers/Tenant/Diagnostics/Overview/utils/prepareTopicSchemaInfo.ts +2 -3
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +0 -6
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +95 -83
- package/dist/containers/Tenant/Query/Issues/Issues.tsx +27 -23
- package/dist/containers/Tenant/Query/Issues/models.ts +0 -11
- package/dist/containers/Tenant/Query/Preview/Preview.tsx +3 -3
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +2 -2
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.tsx +99 -0
- package/dist/containers/Tenant/Tenant.tsx +1 -5
- package/dist/containers/Tenant/TenantPages.tsx +9 -14
- package/dist/containers/Tenant/i18n/en.json +11 -0
- package/dist/containers/Tenant/i18n/index.ts +11 -0
- package/dist/containers/Tenant/i18n/ru.json +11 -0
- package/dist/containers/Tenant/utils/schema.ts +24 -0
- package/dist/containers/Tenant/utils/schemaActions.ts +28 -24
- package/dist/containers/Tenants/Tenants.tsx +1 -4
- package/dist/services/api.ts +6 -7
- package/dist/store/index.js +1 -1
- package/dist/store/reducers/nodes/nodes.ts +14 -5
- package/dist/store/reducers/nodes/types.ts +22 -3
- package/dist/store/reducers/nodes/utils.ts +23 -10
- package/dist/store/reducers/preview.ts +6 -4
- package/dist/store/reducers/schemaAcl/schemaAcl.ts +17 -0
- package/dist/store/reducers/schemaAcl/types.ts +9 -7
- package/dist/store/reducers/tenant/constants.ts +6 -0
- package/dist/store/reducers/tenant/tenant.ts +15 -0
- package/dist/store/reducers/tenant/types.ts +18 -3
- package/dist/store/state-url-mapping.js +3 -0
- package/dist/types/api/cluster.ts +1 -1
- package/dist/types/api/compute.ts +11 -11
- package/dist/types/api/error.ts +2 -2
- package/dist/types/api/netInfo.ts +3 -3
- package/dist/types/api/nodes.ts +9 -8
- package/dist/types/api/query.ts +1 -1
- package/dist/types/api/schema/schema.ts +3 -0
- package/dist/types/api/schema/shared.ts +3 -3
- package/dist/types/api/schema/table.ts +22 -22
- package/dist/types/api/storage.ts +1 -1
- package/dist/types/assets.d.ts +1 -2
- package/dist/types/store/executeQuery.ts +2 -3
- package/dist/types/store/executeTopQueries.ts +8 -5
- package/dist/types/store/explainQuery.ts +4 -4
- package/dist/types/store/query.ts +4 -3
- package/dist/types/store/shardsWorkload.ts +8 -5
- package/dist/utils/constants.ts +4 -1
- package/dist/utils/error.ts +2 -3
- package/dist/utils/query.ts +3 -9
- package/dist/utils/tests/providers.tsx +6 -9
- package/package.json +6 -2
- package/dist/containers/Tenant/Acl/Acl.js +0 -153
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +0 -94
@@ -10,12 +10,11 @@ import {DEFAULT_IS_TENANT_SUMMARY_COLLAPSED, DEFAULT_SIZE_TENANT_KEY} from '../.
|
|
10
10
|
import {useTypedSelector} from '../../utils/hooks';
|
11
11
|
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
12
12
|
import {disableAutorefresh, getSchema} from '../../store/reducers/schema/schema';
|
13
|
-
import {getSchemaAcl} from '../../store/reducers/schemaAcl/schemaAcl';
|
14
13
|
|
15
14
|
import SplitPane from '../../components/SplitPane';
|
16
15
|
import {AccessDenied} from '../../components/Errors/403';
|
17
16
|
|
18
|
-
import ObjectSummary from './ObjectSummary/ObjectSummary';
|
17
|
+
import {ObjectSummary} from './ObjectSummary/ObjectSummary';
|
19
18
|
import ObjectGeneral from './ObjectGeneral/ObjectGeneral';
|
20
19
|
|
21
20
|
import {
|
@@ -74,12 +73,10 @@ function Tenant(props: TenantProps) {
|
|
74
73
|
|
75
74
|
useEffect(() => {
|
76
75
|
dispatch(getSchema({path: tenantName}));
|
77
|
-
dispatch(getSchemaAcl({path: tenantName}));
|
78
76
|
}, [tenantName, dispatch]);
|
79
77
|
|
80
78
|
useEffect(() => {
|
81
79
|
dispatch(getSchema({path: currentSchemaPath}));
|
82
|
-
dispatch(getSchemaAcl({path: currentSchemaPath}));
|
83
80
|
}, [currentSchemaPath, dispatch]);
|
84
81
|
|
85
82
|
useEffect(() => {
|
@@ -124,7 +121,6 @@ function Tenant(props: TenantProps) {
|
|
124
121
|
onCollapseSummary={onCollapseSummaryHandler}
|
125
122
|
onExpandSummary={onExpandSummaryHandler}
|
126
123
|
isCollapsed={summaryVisibilityState.collapsed}
|
127
|
-
additionalTenantInfo={props.additionalTenantInfo}
|
128
124
|
/>
|
129
125
|
<ObjectGeneral
|
130
126
|
type={preloadedPathType || currentPathType}
|
@@ -1,31 +1,26 @@
|
|
1
1
|
import routes, {createHref} from '../../routes';
|
2
|
+
import {TENANT_SUMMARY_TABS_IDS} from '../../store/reducers/tenant/constants';
|
2
3
|
|
3
|
-
export
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
}
|
8
|
-
|
9
|
-
export enum TenantTabsGroups {
|
10
|
-
info = 'info',
|
11
|
-
queryTab = 'queryTab',
|
12
|
-
diagnosticsTab = 'diagnosticsTab',
|
13
|
-
}
|
4
|
+
export const TenantTabsGroups = {
|
5
|
+
summaryTab: 'summaryTab',
|
6
|
+
queryTab: 'queryTab',
|
7
|
+
diagnosticsTab: 'diagnosticsTab',
|
8
|
+
} as const;
|
14
9
|
|
15
10
|
export const TENANT_INFO_TABS = [
|
16
11
|
{
|
17
|
-
id:
|
12
|
+
id: TENANT_SUMMARY_TABS_IDS.overview,
|
18
13
|
title: 'Overview',
|
19
14
|
},
|
20
15
|
{
|
21
|
-
id:
|
16
|
+
id: TENANT_SUMMARY_TABS_IDS.acl,
|
22
17
|
title: 'ACL',
|
23
18
|
},
|
24
19
|
];
|
25
20
|
|
26
21
|
export const TENANT_SCHEMA_TAB = [
|
27
22
|
{
|
28
|
-
id:
|
23
|
+
id: TENANT_SUMMARY_TABS_IDS.schema,
|
29
24
|
title: 'Schema',
|
30
25
|
},
|
31
26
|
];
|
@@ -0,0 +1,11 @@
|
|
1
|
+
{
|
2
|
+
"acl.owner": "Owner",
|
3
|
+
"acl.empty": "No Acl data",
|
4
|
+
|
5
|
+
"summary.navigation": "Navigation",
|
6
|
+
"summary.showPreview": "Show preview",
|
7
|
+
"summary.copySchemaPath": "Copy schema path",
|
8
|
+
|
9
|
+
"actions.copied" : "The path is copied to the clipboard",
|
10
|
+
"actions.notCopied" : "Couldn’t copy the path"
|
11
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {i18n, Lang} from '../../../utils/i18n';
|
2
|
+
|
3
|
+
import en from './en.json';
|
4
|
+
import ru from './ru.json';
|
5
|
+
|
6
|
+
const COMPONENT = 'ydb-tenant';
|
7
|
+
|
8
|
+
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
|
+
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
10
|
+
|
11
|
+
export default i18n.keyset(COMPONENT);
|
@@ -0,0 +1,11 @@
|
|
1
|
+
{
|
2
|
+
"acl.owner": "Владелец",
|
3
|
+
"acl.empty": "Нет данных об Acl",
|
4
|
+
|
5
|
+
"summary.navigation": "Навигация",
|
6
|
+
"summary.showPreview": "Показать превью",
|
7
|
+
"summary.copySchemaPath": "Скопировать путь",
|
8
|
+
|
9
|
+
"actions.copied": "Путь успешно скопирован",
|
10
|
+
"actions.notCopied": "Не получилось скопировать путь"
|
11
|
+
}
|
@@ -32,6 +32,9 @@ const pathTypeToNodeType: Record<EPathType, NavigationTreeNodeType | undefined>
|
|
32
32
|
|
33
33
|
[EPathType.EPathTypeCdcStream]: 'topic',
|
34
34
|
[EPathType.EPathTypePersQueueGroup]: 'topic',
|
35
|
+
|
36
|
+
[EPathType.EPathTypeExternalDataSource]: 'external_data_source',
|
37
|
+
[EPathType.EPathTypeExternalTable]: 'external_table',
|
35
38
|
};
|
36
39
|
|
37
40
|
export const mapPathTypeToNavigationTreeType = (
|
@@ -64,6 +67,8 @@ const pathTypeToEntityName: Record<EPathType, string | undefined> = {
|
|
64
67
|
[EPathType.EPathTypeColumnTable]: 'Columntable',
|
65
68
|
[EPathType.EPathTypeCdcStream]: 'Changefeed',
|
66
69
|
[EPathType.EPathTypePersQueueGroup]: 'Topic',
|
70
|
+
[EPathType.EPathTypeExternalDataSource]: 'External Data Source',
|
71
|
+
[EPathType.EPathTypeExternalTable]: 'External Table',
|
67
72
|
};
|
68
73
|
|
69
74
|
export const mapPathTypeToEntityName = (
|
@@ -90,6 +95,8 @@ const pathTypeToIsTable: Record<EPathType, boolean> = {
|
|
90
95
|
[EPathType.EPathTypeTable]: true,
|
91
96
|
[EPathType.EPathTypeColumnTable]: true,
|
92
97
|
|
98
|
+
[EPathType.EPathTypeExternalTable]: true,
|
99
|
+
|
93
100
|
[EPathType.EPathTypeInvalid]: false,
|
94
101
|
[EPathType.EPathTypeDir]: false,
|
95
102
|
[EPathType.EPathTypeSubDomain]: false,
|
@@ -98,6 +105,7 @@ const pathTypeToIsTable: Record<EPathType, boolean> = {
|
|
98
105
|
[EPathType.EPathTypeColumnStore]: false,
|
99
106
|
[EPathType.EPathTypeCdcStream]: false,
|
100
107
|
[EPathType.EPathTypePersQueueGroup]: false,
|
108
|
+
[EPathType.EPathTypeExternalDataSource]: false,
|
101
109
|
};
|
102
110
|
|
103
111
|
export const isTableType = (pathType?: EPathType) =>
|
@@ -130,6 +138,8 @@ const pathTypeToIsColumn: Record<EPathType, boolean> = {
|
|
130
138
|
[EPathType.EPathTypeExtSubDomain]: false,
|
131
139
|
[EPathType.EPathTypeCdcStream]: false,
|
132
140
|
[EPathType.EPathTypePersQueueGroup]: false,
|
141
|
+
[EPathType.EPathTypeExternalDataSource]: false,
|
142
|
+
[EPathType.EPathTypeExternalTable]: false,
|
133
143
|
};
|
134
144
|
|
135
145
|
export const isColumnEntityType = (type?: EPathType) => (type && pathTypeToIsColumn[type]) ?? false;
|
@@ -148,6 +158,8 @@ const pathTypeToIsDatabase: Record<EPathType, boolean> = {
|
|
148
158
|
[EPathType.EPathTypeTableIndex]: false,
|
149
159
|
[EPathType.EPathTypeCdcStream]: false,
|
150
160
|
[EPathType.EPathTypePersQueueGroup]: false,
|
161
|
+
[EPathType.EPathTypeExternalDataSource]: false,
|
162
|
+
[EPathType.EPathTypeExternalTable]: false,
|
151
163
|
};
|
152
164
|
|
153
165
|
export const isDatabaseEntityType = (type?: EPathType) =>
|
@@ -171,6 +183,8 @@ const pathTypeToEntityWithMergedImplementation: Record<EPathType, boolean> = {
|
|
171
183
|
[EPathType.EPathTypeSubDomain]: false,
|
172
184
|
[EPathType.EPathTypeTableIndex]: false,
|
173
185
|
[EPathType.EPathTypeExtSubDomain]: false,
|
186
|
+
[EPathType.EPathTypeExternalDataSource]: false,
|
187
|
+
[EPathType.EPathTypeExternalTable]: false,
|
174
188
|
};
|
175
189
|
|
176
190
|
export const isEntityWithMergedImplementation = (type?: EPathType) =>
|
@@ -190,6 +204,9 @@ const pathTypeToChildless: Record<EPathType, boolean> = {
|
|
190
204
|
[EPathType.EPathTypeCdcStream]: true,
|
191
205
|
[EPathType.EPathTypePersQueueGroup]: true,
|
192
206
|
|
207
|
+
[EPathType.EPathTypeExternalDataSource]: true,
|
208
|
+
[EPathType.EPathTypeExternalTable]: true,
|
209
|
+
|
193
210
|
[EPathType.EPathTypeInvalid]: false,
|
194
211
|
[EPathType.EPathTypeColumnStore]: false,
|
195
212
|
[EPathType.EPathTypeColumnTable]: false,
|
@@ -217,7 +234,14 @@ const mapPathTypeToIsWithTopic: Record<EPathType, boolean> = {
|
|
217
234
|
[EPathType.EPathTypeSubDomain]: false,
|
218
235
|
[EPathType.EPathTypeTableIndex]: false,
|
219
236
|
[EPathType.EPathTypeExtSubDomain]: false,
|
237
|
+
|
238
|
+
[EPathType.EPathTypeExternalDataSource]: false,
|
239
|
+
[EPathType.EPathTypeExternalTable]: false,
|
220
240
|
};
|
221
241
|
|
222
242
|
export const isPathTypeWithTopic = (type?: EPathType) =>
|
223
243
|
(type && mapPathTypeToIsWithTopic[type]) ?? false;
|
244
|
+
|
245
|
+
// ====================
|
246
|
+
|
247
|
+
export const isExternalTable = (type?: EPathType) => type === EPathType.EPathTypeExternalTable;
|
@@ -1,15 +1,16 @@
|
|
1
1
|
import {Dispatch} from 'react';
|
2
|
+
import copy from 'copy-to-clipboard';
|
3
|
+
|
2
4
|
import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-components';
|
3
5
|
|
4
6
|
import {changeUserInput} from '../../../store/reducers/executeQuery';
|
5
7
|
import {setShowPreview} from '../../../store/reducers/schema/schema';
|
6
8
|
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
|
7
|
-
import {
|
8
|
-
TENANT_QUERY_TABS_ID,
|
9
|
-
TENANT_PAGES_IDS,
|
10
|
-
} from '../../../store/reducers/tenant/constants';
|
9
|
+
import {TENANT_QUERY_TABS_ID, TENANT_PAGES_IDS} from '../../../store/reducers/tenant/constants';
|
11
10
|
import createToast from '../../../utils/createToast';
|
12
11
|
|
12
|
+
import i18n from '../i18n';
|
13
|
+
|
13
14
|
const createTableTemplate = (path: string) => {
|
14
15
|
return `CREATE TABLE \`${path}/my_table\`
|
15
16
|
(
|
@@ -51,22 +52,20 @@ const bindActions = (
|
|
51
52
|
selectQuery: inputQuery(selectQueryTemplate),
|
52
53
|
upsertQuery: inputQuery(upsertQueryTemplate),
|
53
54
|
copyPath: () => {
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
title: 'Couldn’t copy the path',
|
67
|
-
type: 'error',
|
68
|
-
});
|
55
|
+
try {
|
56
|
+
copy(path);
|
57
|
+
createToast({
|
58
|
+
name: 'Copied',
|
59
|
+
title: i18n('actions.copied'),
|
60
|
+
type: 'success',
|
61
|
+
});
|
62
|
+
} catch {
|
63
|
+
createToast({
|
64
|
+
name: 'Not copied',
|
65
|
+
title: i18n('actions.notCopied'),
|
66
|
+
type: 'error',
|
69
67
|
});
|
68
|
+
}
|
70
69
|
},
|
71
70
|
openPreview: () => {
|
72
71
|
dispatch(setShowPreview(true));
|
@@ -84,23 +83,25 @@ export const getActions =
|
|
84
83
|
(path: string, type: NavigationTreeNodeType) => {
|
85
84
|
const actions = bindActions(path, dispatch, setActivePath);
|
86
85
|
const copyItem = {text: 'Copy path', action: actions.copyPath};
|
86
|
+
const openPreview = {text: 'Open preview', action: actions.openPreview};
|
87
|
+
const selectQuery = {text: 'Select query...', action: actions.selectQuery};
|
87
88
|
|
88
89
|
const DIR_SET: ActionsSet = [
|
89
90
|
[copyItem],
|
90
91
|
[{text: 'Create table...', action: actions.createTable}],
|
91
92
|
];
|
92
93
|
const TABLE_SET: ActionsSet = [
|
93
|
-
[
|
94
|
+
[openPreview, copyItem],
|
94
95
|
[
|
95
96
|
{text: 'Alter table...', action: actions.alterTable},
|
96
|
-
|
97
|
+
selectQuery,
|
97
98
|
{text: 'Upsert query...', action: actions.upsertQuery},
|
98
99
|
],
|
99
100
|
];
|
100
101
|
|
101
|
-
const
|
102
|
+
const EXTERNAL_TABLE_SET = [[openPreview, copyItem], [selectQuery]];
|
102
103
|
|
103
|
-
const
|
104
|
+
const JUST_COPY: ActionsSet = [copyItem];
|
104
105
|
|
105
106
|
// verbose mapping to guarantee a correct actions set for new node types
|
106
107
|
// TS will error when a new type is added in the lib but is not mapped here
|
@@ -114,7 +115,10 @@ export const getActions =
|
|
114
115
|
index_table: JUST_COPY,
|
115
116
|
topic: JUST_COPY,
|
116
117
|
|
117
|
-
index:
|
118
|
+
index: JUST_COPY,
|
119
|
+
|
120
|
+
external_table: EXTERNAL_TABLE_SET,
|
121
|
+
external_data_source: JUST_COPY,
|
118
122
|
};
|
119
123
|
|
120
124
|
return nodeTypeToActions[type];
|
@@ -31,7 +31,7 @@ import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
|
31
31
|
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
32
32
|
import {clusterName} from '../../store';
|
33
33
|
|
34
|
-
import {
|
34
|
+
import {getTenantPath} from '../Tenant/TenantPages';
|
35
35
|
|
36
36
|
import './Tenants.scss';
|
37
37
|
|
@@ -80,8 +80,6 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
80
80
|
};
|
81
81
|
|
82
82
|
const renderTable = () => {
|
83
|
-
const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
|
84
|
-
|
85
83
|
const getTenantBackend = (tenant: PreparedTenant) => {
|
86
84
|
const backend = tenant.MonitoringEndpoint ?? tenant.backend;
|
87
85
|
return additionalTenantsProps?.prepareTenantBackend?.(backend);
|
@@ -106,7 +104,6 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
106
104
|
path={getTenantPath({
|
107
105
|
name: row.Name,
|
108
106
|
backend,
|
109
|
-
[TenantTabsGroups.info]: initialTenantInfoTab,
|
110
107
|
})}
|
111
108
|
/>
|
112
109
|
{additionalTenantsProps?.getMonitoringLink?.(row.Name, row.Type)}
|
package/dist/services/api.ts
CHANGED
@@ -28,7 +28,7 @@ import type {DescribeTopicResult} from '../types/api/topic';
|
|
28
28
|
import type {TEvPDiskStateResponse} from '../types/api/pdisk';
|
29
29
|
import type {TEvVDiskStateResponse} from '../types/api/vdisk';
|
30
30
|
import type {TUserToken} from '../types/api/whoami';
|
31
|
-
import type {NodesApiRequestParams} from '../store/reducers/nodes/types';
|
31
|
+
import type {ComputeApiRequestParams, NodesApiRequestParams} from '../store/reducers/nodes/types';
|
32
32
|
import type {StorageApiRequestParams} from '../store/reducers/storage/types';
|
33
33
|
|
34
34
|
import {backend as BACKEND} from '../store';
|
@@ -82,25 +82,24 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
82
82
|
});
|
83
83
|
}
|
84
84
|
getNodes(
|
85
|
-
{
|
85
|
+
{visibleEntities, type = 'any', tablets = true, ...params}: NodesApiRequestParams,
|
86
86
|
{concurrentId}: AxiosOptions = {},
|
87
87
|
) {
|
88
88
|
return this.get<TNodesInfo>(
|
89
89
|
this.getPath('/viewer/json/nodes?enums=true'),
|
90
90
|
{
|
91
|
-
tenant,
|
92
91
|
with: visibleEntities,
|
93
|
-
storage,
|
94
92
|
type,
|
95
93
|
tablets,
|
94
|
+
...params,
|
96
95
|
},
|
97
96
|
{
|
98
97
|
concurrentId,
|
99
98
|
},
|
100
99
|
);
|
101
100
|
}
|
102
|
-
getCompute(
|
103
|
-
return this.get<TComputeInfo>(this.getPath('/viewer/json/compute?enums=true'),
|
101
|
+
getCompute(params: ComputeApiRequestParams) {
|
102
|
+
return this.get<TComputeInfo>(this.getPath('/viewer/json/compute?enums=true'), params);
|
104
103
|
}
|
105
104
|
getStorageInfo(
|
106
105
|
{tenant, visibleEntities, nodeId}: StorageApiRequestParams,
|
@@ -189,7 +188,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
189
188
|
{
|
190
189
|
path,
|
191
190
|
},
|
192
|
-
{concurrentId: `getSchemaAcl
|
191
|
+
{concurrentId: `getSchemaAcl`},
|
193
192
|
);
|
194
193
|
}
|
195
194
|
getHeatmapData({path}: {path: string}) {
|
package/dist/store/index.js
CHANGED
@@ -32,6 +32,6 @@ function configureStore(aRootReducer = rootReducer, singleClusterMode = true) {
|
|
32
32
|
export const webVersion = window.web_version;
|
33
33
|
export const customBackend = window.custom_backend;
|
34
34
|
|
35
|
-
export * from
|
35
|
+
export * from './reducers';
|
36
36
|
|
37
37
|
export default configureStore;
|
@@ -2,10 +2,16 @@ import type {Reducer} from 'redux';
|
|
2
2
|
|
3
3
|
import '../../../services/api';
|
4
4
|
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
5
|
+
import {EVersion} from '../../../types/api/compute';
|
5
6
|
|
6
7
|
import {createRequestActionTypes, createApiRequest} from '../../utils';
|
7
8
|
|
8
|
-
import type {
|
9
|
+
import type {
|
10
|
+
ComputeApiRequestParams,
|
11
|
+
NodesAction,
|
12
|
+
NodesApiRequestParams,
|
13
|
+
NodesState,
|
14
|
+
} from './types';
|
9
15
|
import {prepareComputeNodesData, prepareNodesData} from './utils';
|
10
16
|
|
11
17
|
export const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
|
@@ -80,17 +86,20 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
|
|
80
86
|
}
|
81
87
|
};
|
82
88
|
|
83
|
-
export function getNodes({
|
89
|
+
export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
|
84
90
|
return createApiRequest({
|
85
|
-
request: window.api.getNodes({
|
91
|
+
request: window.api.getNodes({
|
92
|
+
type,
|
93
|
+
...params,
|
94
|
+
}),
|
86
95
|
actions: FETCH_NODES,
|
87
96
|
dataHandler: prepareNodesData,
|
88
97
|
});
|
89
98
|
}
|
90
99
|
|
91
|
-
export function getComputeNodes(
|
100
|
+
export function getComputeNodes({version = EVersion.v2, ...params}: ComputeApiRequestParams) {
|
92
101
|
return createApiRequest({
|
93
|
-
request: window.api.getCompute(
|
102
|
+
request: window.api.getCompute({version, ...params}),
|
94
103
|
actions: FETCH_NODES,
|
95
104
|
dataHandler: prepareComputeNodesData,
|
96
105
|
});
|
@@ -1,6 +1,9 @@
|
|
1
1
|
import type {IResponseError} from '../../../types/api/error';
|
2
2
|
import type {TEndpoint, TPoolStats} from '../../../types/api/nodes';
|
3
|
-
import type {
|
3
|
+
import type {
|
4
|
+
EVersion,
|
5
|
+
TTabletStateInfo as TComputeTabletStateInfo,
|
6
|
+
} from '../../../types/api/compute';
|
4
7
|
import type {TTabletStateInfo as TFullTabletStateInfo} from '../../../types/api/tablet';
|
5
8
|
import type {EFlag} from '../../../types/api/enums';
|
6
9
|
import type {ApiRequestAction} from '../../utils';
|
@@ -46,17 +49,33 @@ export interface NodesState {
|
|
46
49
|
|
47
50
|
export type NodeType = 'static' | 'dynamic' | 'any';
|
48
51
|
|
49
|
-
|
52
|
+
interface RequestParams {
|
53
|
+
filter?: string; // NodeId or Host
|
54
|
+
uptime?: number; // return nodes with less uptime in seconds
|
55
|
+
problems_only?: boolean; // return nodes with SystemState !== EFlag.Green
|
56
|
+
sort?: string; // Sort by one of ESort params (may differ for /nodes and /compute)
|
57
|
+
|
58
|
+
offser?: number;
|
59
|
+
limit?: number;
|
60
|
+
}
|
61
|
+
|
62
|
+
export interface NodesApiRequestParams extends RequestParams {
|
50
63
|
tenant?: string;
|
51
64
|
type?: NodeType;
|
52
|
-
visibleEntities?: VisibleEntities;
|
65
|
+
visibleEntities?: VisibleEntities; // "with" param
|
53
66
|
storage?: boolean;
|
54
67
|
tablets?: boolean;
|
55
68
|
}
|
56
69
|
|
70
|
+
export interface ComputeApiRequestParams extends RequestParams {
|
71
|
+
path: string;
|
72
|
+
version?: EVersion; // only v2 works with filters
|
73
|
+
}
|
74
|
+
|
57
75
|
export interface NodesHandledResponse {
|
58
76
|
Nodes?: NodesPreparedEntity[];
|
59
77
|
TotalNodes: number;
|
78
|
+
FoundNodes?: number;
|
60
79
|
}
|
61
80
|
|
62
81
|
type NodesApiRequestAction = ApiRequestAction<
|
@@ -1,28 +1,40 @@
|
|
1
|
-
import type {TComputeInfo} from '../../../types/api/compute';
|
1
|
+
import type {TComputeInfo, TComputeNodeInfo} from '../../../types/api/compute';
|
2
2
|
import type {TNodesInfo} from '../../../types/api/nodes';
|
3
3
|
import {calcUptime} from '../../../utils';
|
4
4
|
|
5
5
|
import type {NodesHandledResponse, NodesPreparedEntity} from './types';
|
6
6
|
|
7
|
+
const prepareComputeNode = (node: TComputeNodeInfo, tenantName?: string) => {
|
8
|
+
return {
|
9
|
+
...node,
|
10
|
+
// v2 response has tenant name, v1 - doesn't
|
11
|
+
TenantName: node.Tenant ?? tenantName,
|
12
|
+
SystemState: node?.Overall,
|
13
|
+
Uptime: calcUptime(node?.StartTime),
|
14
|
+
};
|
15
|
+
};
|
16
|
+
|
7
17
|
export const prepareComputeNodesData = (data: TComputeInfo): NodesHandledResponse => {
|
8
18
|
const preparedNodes: NodesPreparedEntity[] = [];
|
9
19
|
|
10
|
-
|
20
|
+
// First try to parse v2 response in case backend supports it
|
21
|
+
// Else parse v1 response
|
22
|
+
if (data.Nodes) {
|
23
|
+
data.Nodes.forEach((node) => {
|
24
|
+
preparedNodes.push(prepareComputeNode(node));
|
25
|
+
});
|
26
|
+
} else if (data.Tenants) {
|
11
27
|
for (const tenant of data.Tenants) {
|
12
28
|
tenant.Nodes?.forEach((node) => {
|
13
|
-
preparedNodes.push(
|
14
|
-
...node,
|
15
|
-
TenantName: tenant.Name,
|
16
|
-
SystemState: node?.Overall,
|
17
|
-
Uptime: calcUptime(node?.StartTime),
|
18
|
-
});
|
29
|
+
preparedNodes.push(prepareComputeNode(node, tenant.Name));
|
19
30
|
});
|
20
31
|
}
|
21
32
|
}
|
22
33
|
|
23
34
|
return {
|
24
35
|
Nodes: preparedNodes,
|
25
|
-
TotalNodes: preparedNodes.length,
|
36
|
+
TotalNodes: Number(data.TotalNodes) || preparedNodes.length,
|
37
|
+
FoundNodes: Number(data.FoundNodes),
|
26
38
|
};
|
27
39
|
};
|
28
40
|
|
@@ -41,6 +53,7 @@ export const prepareNodesData = (data: TNodesInfo): NodesHandledResponse => {
|
|
41
53
|
|
42
54
|
return {
|
43
55
|
Nodes: preparedNodes,
|
44
|
-
TotalNodes: Number(data.TotalNodes)
|
56
|
+
TotalNodes: Number(data.TotalNodes) || preparedNodes.length,
|
57
|
+
FoundNodes: Number(data.FoundNodes),
|
45
58
|
};
|
46
59
|
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import '../../services/api';
|
2
2
|
|
3
|
-
import type {
|
4
|
-
import type {IQueryResult} from '../../types/store/query';
|
3
|
+
import type {ExecuteActions} from '../../types/api/query';
|
4
|
+
import type {IQueryResult, QueryErrorResponse} from '../../types/store/query';
|
5
5
|
import {parseQueryAPIExecuteResponse} from '../../utils/query';
|
6
6
|
|
7
7
|
import {createRequestActionTypes, createApiRequest, ApiRequestAction} from '../utils';
|
@@ -16,7 +16,9 @@ const initialState = {
|
|
16
16
|
|
17
17
|
const preview = (
|
18
18
|
state = initialState,
|
19
|
-
action:
|
19
|
+
action:
|
20
|
+
| ApiRequestAction<typeof SEND_QUERY, IQueryResult, QueryErrorResponse>
|
21
|
+
| ReturnType<typeof setQueryOptions>,
|
20
22
|
) => {
|
21
23
|
switch (action.type) {
|
22
24
|
case SEND_QUERY.REQUEST: {
|
@@ -57,7 +59,7 @@ interface SendQueryParams {
|
|
57
59
|
query?: string;
|
58
60
|
database?: string;
|
59
61
|
action?: ExecuteActions;
|
60
|
-
}
|
62
|
+
}
|
61
63
|
|
62
64
|
export const sendQuery = ({query, database, action}: SendQueryParams) => {
|
63
65
|
return createApiRequest({
|
@@ -6,6 +6,7 @@ import {createRequestActionTypes, createApiRequest} from '../../utils';
|
|
6
6
|
import type {SchemaAclAction, SchemaAclState} from './types';
|
7
7
|
|
8
8
|
export const FETCH_SCHEMA_ACL = createRequestActionTypes('schemaAcl', 'FETCH_SCHEMA_ACL');
|
9
|
+
const SET_ACL_WAS_NOT_LOADED = 'schemaAcl/SET_DATA_WAS_NOT_LOADED';
|
9
10
|
|
10
11
|
const initialState = {
|
11
12
|
loading: false,
|
@@ -34,12 +35,22 @@ const schemaAcl: Reducer<SchemaAclState, SchemaAclAction> = (state = initialStat
|
|
34
35
|
};
|
35
36
|
}
|
36
37
|
case FETCH_SCHEMA_ACL.FAILURE: {
|
38
|
+
if (action.error?.isCancelled) {
|
39
|
+
return state;
|
40
|
+
}
|
41
|
+
|
37
42
|
return {
|
38
43
|
...state,
|
39
44
|
error: action.error,
|
40
45
|
loading: false,
|
41
46
|
};
|
42
47
|
}
|
48
|
+
case SET_ACL_WAS_NOT_LOADED: {
|
49
|
+
return {
|
50
|
+
...state,
|
51
|
+
wasLoaded: false,
|
52
|
+
};
|
53
|
+
}
|
43
54
|
default:
|
44
55
|
return state;
|
45
56
|
}
|
@@ -52,4 +63,10 @@ export function getSchemaAcl({path}: {path: string}) {
|
|
52
63
|
});
|
53
64
|
}
|
54
65
|
|
66
|
+
export const setAclWasNotLoaded = () => {
|
67
|
+
return {
|
68
|
+
type: SET_ACL_WAS_NOT_LOADED,
|
69
|
+
} as const;
|
70
|
+
};
|
71
|
+
|
55
72
|
export default schemaAcl;
|
@@ -2,14 +2,16 @@ import type {TACE, TMetaInfo} from '../../../types/api/acl';
|
|
2
2
|
import type {IResponseError} from '../../../types/api/error';
|
3
3
|
import type {ApiRequestAction} from '../../utils';
|
4
4
|
|
5
|
-
import {FETCH_SCHEMA_ACL} from './schemaAcl';
|
5
|
+
import {FETCH_SCHEMA_ACL, setAclWasNotLoaded} from './schemaAcl';
|
6
6
|
|
7
7
|
export interface SchemaAclState {
|
8
|
-
loading: boolean
|
9
|
-
wasLoaded: boolean
|
10
|
-
acl?: TACE[]
|
11
|
-
owner?: string
|
12
|
-
error?: IResponseError
|
8
|
+
loading: boolean;
|
9
|
+
wasLoaded: boolean;
|
10
|
+
acl?: TACE[];
|
11
|
+
owner?: string;
|
12
|
+
error?: IResponseError;
|
13
13
|
}
|
14
14
|
|
15
|
-
export type SchemaAclAction =
|
15
|
+
export type SchemaAclAction =
|
16
|
+
| ApiRequestAction<typeof FETCH_SCHEMA_ACL, TMetaInfo, IResponseError>
|
17
|
+
| ReturnType<typeof setAclWasNotLoaded>;
|