ydb-embedded-ui 4.10.0 → 4.11.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +30 -0
- package/dist/components/InfoViewer/formatters/schema.ts +3 -1
- 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/components/TableWithControlsLayout/TableWithControlsLayout.scss +32 -0
- package/dist/components/TableWithControlsLayout/TableWithControlsLayout.tsx +43 -0
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +2 -2
- package/dist/containers/Cluster/Cluster.scss +4 -5
- package/dist/containers/Cluster/Cluster.tsx +3 -22
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +4 -0
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +14 -3
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +1 -1
- package/dist/containers/Cluster/utils.tsx +0 -11
- package/dist/containers/Header/Header.scss +1 -5
- 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.scss +1 -24
- package/dist/containers/Nodes/Nodes.tsx +29 -39
- package/dist/containers/Storage/EmptyFilter/i18n/en.json +2 -2
- package/dist/containers/Storage/EmptyFilter/i18n/ru.json +2 -2
- package/dist/containers/Storage/Storage.scss +1 -14
- package/dist/containers/Storage/Storage.tsx +15 -18
- package/dist/containers/Storage/StorageGroups/i18n/en.json +5 -5
- package/dist/containers/Storage/StorageGroups/i18n/ru.json +5 -5
- package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +3 -1
- package/dist/containers/Storage/{StorageVisibleEntityFilter/StorageVisibleEntityFilter.tsx → StorageVisibleEntitiesFilter/StorageVisibleEntitiesFilter.tsx} +4 -2
- 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/Diagnostics.scss +6 -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 +3 -18
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +95 -88
- 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/Query/i18n/en.json +1 -1
- package/dist/containers/Tenant/Query/i18n/ru.json +1 -1
- 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.scss +1 -13
- package/dist/containers/Tenants/Tenants.tsx +18 -28
- package/dist/services/api.ts +6 -7
- package/dist/store/index.js +1 -1
- package/dist/store/reducers/nodes/nodes.ts +12 -111
- package/dist/store/reducers/nodes/selectors.ts +74 -0
- package/dist/store/reducers/nodes/types.ts +22 -3
- package/dist/store/reducers/nodes/utils.ts +59 -0
- 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/storage/selectors.ts +1 -1
- 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 +27 -2
- package/dist/types/api/error.ts +2 -2
- package/dist/types/api/netInfo.ts +3 -3
- package/dist/types/api/nodes.ts +13 -1
- package/dist/types/api/query.ts +1 -1
- package/dist/types/api/schema/cdcStream.ts +32 -0
- package/dist/types/api/schema/columnEntity.ts +138 -0
- package/dist/types/api/schema/externalDataSource.ts +24 -0
- package/dist/types/api/schema/externalTable.ts +14 -0
- package/dist/types/api/schema/index.ts +10 -0
- package/dist/types/api/schema/persQueueGroup.ts +191 -0
- package/dist/types/api/schema/schema.ts +302 -0
- package/dist/types/api/schema/shared.ts +42 -0
- package/dist/types/api/schema/table.ts +616 -0
- package/dist/types/api/schema/tableIndex.ts +33 -0
- 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/assets/icons/versions.svg +0 -3
- package/dist/containers/Tenant/Acl/Acl.js +0 -153
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +0 -94
- package/dist/types/api/schema.ts +0 -1326
@@ -0,0 +1,99 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import DataTable, {Column} from '@gravity-ui/react-data-table';
|
4
|
+
|
5
|
+
import type {EPathType, TColumnDescription} from '../../../../types/api/schema';
|
6
|
+
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';
|
7
|
+
|
8
|
+
import {Icon} from '../../../../components/Icon';
|
9
|
+
|
10
|
+
import {isExternalTable} from '../../utils/schema';
|
11
|
+
|
12
|
+
import './SchemaViewer.scss';
|
13
|
+
|
14
|
+
const b = cn('schema-viewer');
|
15
|
+
|
16
|
+
const SchemaViewerColumns = {
|
17
|
+
id: 'Id',
|
18
|
+
name: 'Name',
|
19
|
+
key: 'Key',
|
20
|
+
type: 'Type',
|
21
|
+
notNull: 'NotNull',
|
22
|
+
};
|
23
|
+
|
24
|
+
interface SchemaViewerProps {
|
25
|
+
keyColumnIds?: number[];
|
26
|
+
columns?: TColumnDescription[];
|
27
|
+
type?: EPathType;
|
28
|
+
}
|
29
|
+
|
30
|
+
export const SchemaViewer = ({keyColumnIds = [], columns = [], type}: SchemaViewerProps) => {
|
31
|
+
let dataTableColumns: Column<TColumnDescription>[] = [
|
32
|
+
{
|
33
|
+
name: SchemaViewerColumns.id,
|
34
|
+
width: 40,
|
35
|
+
},
|
36
|
+
{
|
37
|
+
name: SchemaViewerColumns.key,
|
38
|
+
width: 40,
|
39
|
+
sortAccessor: (row) => {
|
40
|
+
return row.Id && keyColumnIds.includes(row.Id) ? 1 : 0;
|
41
|
+
},
|
42
|
+
render: ({row}) => {
|
43
|
+
return row.Id && keyColumnIds.includes(row.Id) ? (
|
44
|
+
<div className={b('key-icon')}>
|
45
|
+
<Icon name="key" viewBox="0 0 12 7" width={12} height={7} />
|
46
|
+
</div>
|
47
|
+
) : null;
|
48
|
+
},
|
49
|
+
},
|
50
|
+
{
|
51
|
+
name: SchemaViewerColumns.name,
|
52
|
+
width: 100,
|
53
|
+
},
|
54
|
+
{
|
55
|
+
name: SchemaViewerColumns.type,
|
56
|
+
width: 100,
|
57
|
+
},
|
58
|
+
{
|
59
|
+
name: SchemaViewerColumns.notNull,
|
60
|
+
width: 100,
|
61
|
+
render: ({row}) => {
|
62
|
+
if (row.NotNull) {
|
63
|
+
return '\u2713';
|
64
|
+
}
|
65
|
+
|
66
|
+
return undefined;
|
67
|
+
},
|
68
|
+
},
|
69
|
+
];
|
70
|
+
|
71
|
+
if (isExternalTable(type)) {
|
72
|
+
// External tables don't have key columns
|
73
|
+
dataTableColumns = dataTableColumns.filter(
|
74
|
+
(column) => column.name !== SchemaViewerColumns.key,
|
75
|
+
);
|
76
|
+
}
|
77
|
+
|
78
|
+
// Display key columns first
|
79
|
+
const tableData = columns.sort((column) => {
|
80
|
+
if (column.Id && keyColumnIds.includes(column.Id)) {
|
81
|
+
return 1;
|
82
|
+
}
|
83
|
+
return -1;
|
84
|
+
});
|
85
|
+
|
86
|
+
return (
|
87
|
+
<div className={b()}>
|
88
|
+
<DataTable
|
89
|
+
theme="yandex-cloud"
|
90
|
+
data={tableData}
|
91
|
+
columns={dataTableColumns}
|
92
|
+
settings={DEFAULT_TABLE_SETTINGS}
|
93
|
+
initialSortOrder={{columnId: SchemaViewerColumns.key, order: DataTable.DESCENDING}}
|
94
|
+
/>
|
95
|
+
</div>
|
96
|
+
);
|
97
|
+
};
|
98
|
+
|
99
|
+
export default SchemaViewer;
|
@@ -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];
|
@@ -1,9 +1,6 @@
|
|
1
1
|
@import '../../styles/mixins.scss';
|
2
2
|
|
3
3
|
.tenants {
|
4
|
-
height: 100%;
|
5
|
-
@include flex-container();
|
6
|
-
|
7
4
|
&__format-label {
|
8
5
|
margin-right: 15px;
|
9
6
|
}
|
@@ -28,16 +25,7 @@
|
|
28
25
|
}
|
29
26
|
}
|
30
27
|
|
31
|
-
&
|
32
|
-
@include controls();
|
33
|
-
}
|
34
|
-
|
35
|
-
&__table-wrapper {
|
36
|
-
overflow: auto;
|
37
|
-
flex-grow: 1;
|
38
|
-
|
39
|
-
@include freeze-nth-column(1);
|
40
|
-
|
28
|
+
&__table {
|
41
29
|
@include table-styles;
|
42
30
|
}
|
43
31
|
|
@@ -2,7 +2,7 @@ import cn from 'bem-cn-lite';
|
|
2
2
|
import {useDispatch} from 'react-redux';
|
3
3
|
|
4
4
|
import DataTable, {Column} from '@gravity-ui/react-data-table';
|
5
|
-
import {
|
5
|
+
import {Button} from '@gravity-ui/uikit';
|
6
6
|
|
7
7
|
import EntityStatus from '../../components/EntityStatus/EntityStatus';
|
8
8
|
import {PoolsGraph} from '../../components/PoolsGraph/PoolsGraph';
|
@@ -10,6 +10,7 @@ import {TabletsStatistic} from '../../components/TabletsStatistic';
|
|
10
10
|
import {ProblemFilter} from '../../components/ProblemFilter';
|
11
11
|
import {Illustration} from '../../components/Illustration';
|
12
12
|
import {Search} from '../../components/Search';
|
13
|
+
import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout';
|
13
14
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
14
15
|
|
15
16
|
import type {AdditionalTenantsProps} from '../../types/additionalProps';
|
@@ -30,7 +31,7 @@ import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
|
|
30
31
|
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
31
32
|
import {clusterName} from '../../store';
|
32
33
|
|
33
|
-
import {
|
34
|
+
import {getTenantPath} from '../Tenant/TenantPages';
|
34
35
|
|
35
36
|
import './Tenants.scss';
|
36
37
|
|
@@ -66,7 +67,7 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
66
67
|
|
67
68
|
const renderControls = () => {
|
68
69
|
return (
|
69
|
-
|
70
|
+
<>
|
70
71
|
<Search
|
71
72
|
value={searchValue}
|
72
73
|
onChange={handleSearchChange}
|
@@ -74,13 +75,11 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
74
75
|
className={b('search')}
|
75
76
|
/>
|
76
77
|
<ProblemFilter value={problemFilter} onChange={handleProblemFilterChange} />
|
77
|
-
|
78
|
+
</>
|
78
79
|
);
|
79
80
|
};
|
80
81
|
|
81
82
|
const renderTable = () => {
|
82
|
-
const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
|
83
|
-
|
84
83
|
const getTenantBackend = (tenant: PreparedTenant) => {
|
85
84
|
const backend = tenant.MonitoringEndpoint ?? tenant.backend;
|
86
85
|
return additionalTenantsProps?.prepareTenantBackend?.(backend);
|
@@ -105,7 +104,6 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
105
104
|
path={getTenantPath({
|
106
105
|
name: row.Name,
|
107
106
|
backend,
|
108
|
-
[TenantTabsGroups.info]: initialTenantInfoTab,
|
109
107
|
})}
|
110
108
|
/>
|
111
109
|
{additionalTenantsProps?.getMonitoringLink?.(row.Name, row.Type)}
|
@@ -236,34 +234,26 @@ export const Tenants = ({additionalTenantsProps}: TenantsProps) => {
|
|
236
234
|
}
|
237
235
|
|
238
236
|
return (
|
239
|
-
<
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
/>
|
247
|
-
</div>
|
237
|
+
<DataTable
|
238
|
+
theme="yandex-cloud"
|
239
|
+
data={filteredTenants}
|
240
|
+
columns={columns}
|
241
|
+
settings={DEFAULT_TABLE_SETTINGS}
|
242
|
+
emptyDataMessage="No such tenants"
|
243
|
+
/>
|
248
244
|
);
|
249
245
|
};
|
250
246
|
|
251
|
-
if (loading && !wasLoaded) {
|
252
|
-
return (
|
253
|
-
<div className={'loader'}>
|
254
|
-
<Loader size="l" />
|
255
|
-
</div>
|
256
|
-
);
|
257
|
-
}
|
258
|
-
|
259
247
|
if (error) {
|
260
248
|
return <ResponseError error={error} />;
|
261
249
|
}
|
262
250
|
|
263
251
|
return (
|
264
|
-
<
|
265
|
-
{renderControls()}
|
266
|
-
{
|
267
|
-
|
252
|
+
<TableWithControlsLayout>
|
253
|
+
<TableWithControlsLayout.Controls>{renderControls()}</TableWithControlsLayout.Controls>
|
254
|
+
<TableWithControlsLayout.Table loading={loading && !wasLoaded} className={b('table')}>
|
255
|
+
{renderTable()}
|
256
|
+
</TableWithControlsLayout.Table>
|
257
|
+
</TableWithControlsLayout>
|
268
258
|
);
|
269
259
|
};
|
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;
|