ydb-embedded-ui 4.6.0 → 4.8.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +27 -0
- package/dist/assets/icons/versions.svg +3 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +6 -1
- package/dist/components/Tablet/Tablet.tsx +17 -3
- package/dist/components/TabletsStatistic/TabletsStatistic.tsx +23 -16
- package/dist/containers/App/Content.js +5 -2
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +50 -18
- package/dist/containers/Cluster/Cluster.tsx +6 -13
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +3 -3
- package/dist/containers/Cluster/{utils.ts → utils.tsx} +11 -0
- package/dist/containers/Header/Header.scss +9 -0
- package/dist/containers/Header/Header.tsx +70 -14
- package/dist/containers/Header/breadcrumbs.ts +146 -0
- package/dist/containers/Node/Node.tsx +21 -27
- package/dist/containers/Node/NodePages.ts +10 -6
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
- package/dist/containers/Tablet/Tablet.tsx +35 -27
- package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
- package/dist/containers/TabletsFilters/TabletsFilters.js +13 -15
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +5 -1
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -14
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +9 -16
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +11 -11
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
- package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
- package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
- package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
- package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
- package/dist/containers/Tenant/Query/Query.scss +16 -0
- package/dist/containers/Tenant/Query/Query.tsx +73 -0
- package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +39 -88
- package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
- package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
- package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
- package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
- package/dist/containers/Tenant/Query/i18n/en.json +12 -0
- package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
- package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
- package/dist/containers/Tenant/Tenant.scss +0 -8
- package/dist/containers/Tenant/Tenant.tsx +24 -46
- package/dist/containers/Tenant/TenantPages.tsx +7 -16
- package/dist/containers/Tenant/utils/constants.ts +10 -0
- package/dist/containers/Tenant/utils/schemaActions.ts +9 -4
- package/dist/containers/Tenants/Tenants.js +26 -13
- package/dist/routes.ts +21 -7
- package/dist/services/api.ts +9 -5
- package/dist/store/reducers/executeQuery.ts +18 -4
- package/dist/store/reducers/header/header.ts +31 -0
- package/dist/store/reducers/header/types.ts +54 -0
- package/dist/store/reducers/index.ts +1 -1
- package/dist/store/reducers/node/types.ts +2 -0
- package/dist/store/reducers/settings/settings.ts +8 -3
- package/dist/store/reducers/tablet.ts +18 -1
- package/dist/store/reducers/tenant/constants.ts +9 -1
- package/dist/store/reducers/tenant/tenant.ts +23 -4
- package/dist/store/reducers/tenant/types.ts +9 -5
- package/dist/store/reducers/topic.ts +1 -1
- package/dist/store/state-url-mapping.js +6 -3
- package/dist/types/store/executeQuery.ts +4 -1
- package/dist/types/store/query.ts +5 -0
- package/dist/types/store/tablet.ts +7 -4
- package/dist/utils/constants.ts +5 -1
- package/package.json +2 -1
- package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.scss +0 -9
- package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.tsx +0 -68
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
- package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
- package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
- package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
- package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
- package/dist/store/reducers/header.ts +0 -26
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
import nodesRightIcon from '@gravity-ui/icons/svgs/nodes-right.svg';
|
2
|
+
import databaseIcon from '@gravity-ui/icons/svgs/database.svg';
|
3
|
+
|
4
|
+
import type {
|
5
|
+
BreadcrumbsOptions,
|
6
|
+
ClusterBreadcrumbsOptions,
|
7
|
+
NodeBreadcrumbsOptions,
|
8
|
+
Page,
|
9
|
+
TabletBreadcrumbsOptions,
|
10
|
+
TabletsBreadcrumbsOptions,
|
11
|
+
TenantBreadcrumbsOptions,
|
12
|
+
} from '../../store/reducers/header/types';
|
13
|
+
import routes, {createHref} from '../../routes';
|
14
|
+
|
15
|
+
import {getClusterPath} from '../Cluster/utils';
|
16
|
+
import {getTenantPath} from '../Tenant/TenantPages';
|
17
|
+
import {getDefaultNodePath} from '../Node/NodePages';
|
18
|
+
|
19
|
+
const prepareTenantName = (tenantName: string) => {
|
20
|
+
return tenantName.startsWith('/') ? tenantName.slice(1) : tenantName;
|
21
|
+
};
|
22
|
+
|
23
|
+
export interface RawBreadcrumbItem {
|
24
|
+
text: string;
|
25
|
+
link?: string;
|
26
|
+
icon?: SVGIconData;
|
27
|
+
}
|
28
|
+
|
29
|
+
const getClusterBreadcrumbs = (
|
30
|
+
options: ClusterBreadcrumbsOptions,
|
31
|
+
query = {},
|
32
|
+
): RawBreadcrumbItem[] => {
|
33
|
+
const {clusterName, clusterTab} = options;
|
34
|
+
|
35
|
+
return [
|
36
|
+
{
|
37
|
+
text: clusterName || 'Cluster',
|
38
|
+
link: getClusterPath(clusterTab, query),
|
39
|
+
icon: nodesRightIcon,
|
40
|
+
},
|
41
|
+
];
|
42
|
+
};
|
43
|
+
|
44
|
+
const getTenantBreadcrumbs = (
|
45
|
+
options: TenantBreadcrumbsOptions,
|
46
|
+
query = {},
|
47
|
+
): RawBreadcrumbItem[] => {
|
48
|
+
const {tenantName} = options;
|
49
|
+
|
50
|
+
const text = tenantName ? prepareTenantName(tenantName) : 'Tenant';
|
51
|
+
const link = tenantName ? getTenantPath({...query, name: tenantName}) : undefined;
|
52
|
+
|
53
|
+
return [...getClusterBreadcrumbs(options, query), {text, link, icon: databaseIcon}];
|
54
|
+
};
|
55
|
+
|
56
|
+
const getNodeBreadcrumbs = (options: NodeBreadcrumbsOptions, query = {}): RawBreadcrumbItem[] => {
|
57
|
+
const {tenantName, nodeId} = options;
|
58
|
+
|
59
|
+
let breadcrumbs: RawBreadcrumbItem[];
|
60
|
+
|
61
|
+
// Compute nodes have tenantName, storage nodes doesn't
|
62
|
+
const isStorageNode = !tenantName;
|
63
|
+
|
64
|
+
if (isStorageNode) {
|
65
|
+
breadcrumbs = getClusterBreadcrumbs(options, query);
|
66
|
+
} else {
|
67
|
+
breadcrumbs = getTenantBreadcrumbs(options, query);
|
68
|
+
}
|
69
|
+
|
70
|
+
const text = nodeId ? `Node ${nodeId}` : 'Node';
|
71
|
+
const link = nodeId ? getDefaultNodePath(nodeId, query) : undefined;
|
72
|
+
|
73
|
+
breadcrumbs.push({text, link});
|
74
|
+
|
75
|
+
return breadcrumbs;
|
76
|
+
};
|
77
|
+
|
78
|
+
const getTabletsBreadcrubms = (
|
79
|
+
options: TabletsBreadcrumbsOptions,
|
80
|
+
query = {},
|
81
|
+
): RawBreadcrumbItem[] => {
|
82
|
+
const {tenantName, nodeIds, state, type} = options;
|
83
|
+
|
84
|
+
let breadcrumbs: RawBreadcrumbItem[];
|
85
|
+
|
86
|
+
// Cluster system tablets don't have tenantName
|
87
|
+
if (tenantName) {
|
88
|
+
breadcrumbs = getTenantBreadcrumbs(options, query);
|
89
|
+
} else {
|
90
|
+
breadcrumbs = getClusterBreadcrumbs(options, query);
|
91
|
+
}
|
92
|
+
|
93
|
+
const link = createHref(routes.tabletsFilters, undefined, {
|
94
|
+
nodeIds,
|
95
|
+
state,
|
96
|
+
type,
|
97
|
+
path: tenantName,
|
98
|
+
});
|
99
|
+
|
100
|
+
breadcrumbs.push({text: 'Tablets', link});
|
101
|
+
|
102
|
+
return breadcrumbs;
|
103
|
+
};
|
104
|
+
|
105
|
+
const getTabletBreadcrubms = (
|
106
|
+
options: TabletBreadcrumbsOptions,
|
107
|
+
query = {},
|
108
|
+
): RawBreadcrumbItem[] => {
|
109
|
+
const {tabletId} = options;
|
110
|
+
|
111
|
+
const breadcrumbs = getTabletsBreadcrubms(options, query);
|
112
|
+
|
113
|
+
breadcrumbs.push({
|
114
|
+
text: tabletId || 'Tablet',
|
115
|
+
});
|
116
|
+
|
117
|
+
return breadcrumbs;
|
118
|
+
};
|
119
|
+
|
120
|
+
export const getBreadcrumbs = (
|
121
|
+
page: Page,
|
122
|
+
options: BreadcrumbsOptions,
|
123
|
+
rawBreadcrumbs: RawBreadcrumbItem[] = [],
|
124
|
+
query = {},
|
125
|
+
) => {
|
126
|
+
switch (page) {
|
127
|
+
case 'cluster': {
|
128
|
+
return [...rawBreadcrumbs, ...getClusterBreadcrumbs(options, query)];
|
129
|
+
}
|
130
|
+
case 'tenant': {
|
131
|
+
return [...rawBreadcrumbs, ...getTenantBreadcrumbs(options, query)];
|
132
|
+
}
|
133
|
+
case 'node': {
|
134
|
+
return [...rawBreadcrumbs, ...getNodeBreadcrumbs(options, query)];
|
135
|
+
}
|
136
|
+
case 'tablets': {
|
137
|
+
return [...rawBreadcrumbs, ...getTabletsBreadcrubms(options, query)];
|
138
|
+
}
|
139
|
+
case 'tablet': {
|
140
|
+
return [...rawBreadcrumbs, ...getTabletBreadcrubms(options, query)];
|
141
|
+
}
|
142
|
+
default: {
|
143
|
+
return rawBreadcrumbs;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
-
import {useRouteMatch} from 'react-router';
|
2
|
+
import {useLocation, useRouteMatch} from 'react-router';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
|
-
import {useDispatch
|
4
|
+
import {useDispatch} from 'react-redux';
|
5
5
|
import _ from 'lodash';
|
6
6
|
|
7
7
|
import {Tabs} from '@gravity-ui/uikit';
|
@@ -16,10 +16,12 @@ import {Loader} from '../../components/Loader';
|
|
16
16
|
import {BasicNodeViewer} from '../../components/BasicNodeViewer';
|
17
17
|
|
18
18
|
import {getNodeInfo, resetNode} from '../../store/reducers/node/node';
|
19
|
-
import routes, {createHref} from '../../routes';
|
20
|
-
import {
|
19
|
+
import routes, {createHref, parseQuery} from '../../routes';
|
20
|
+
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
21
21
|
import {AutoFetcher} from '../../utils/autofetcher';
|
22
|
-
import {
|
22
|
+
import {useTypedSelector} from '../../utils/hooks';
|
23
|
+
|
24
|
+
import {clusterTabsIds} from '../Cluster/utils';
|
23
25
|
|
24
26
|
import './Node.scss';
|
25
27
|
|
@@ -36,19 +38,16 @@ interface NodeProps {
|
|
36
38
|
|
37
39
|
function Node(props: NodeProps) {
|
38
40
|
const dispatch = useDispatch();
|
41
|
+
const location = useLocation();
|
39
42
|
|
40
|
-
const wasLoaded =
|
41
|
-
const
|
42
|
-
const error = useSelector((state: any) => state.node.error);
|
43
|
-
|
44
|
-
const node = useSelector((state: any) => state.node?.data?.SystemStateInfo?.[0]);
|
45
|
-
|
46
|
-
const nodeHost = node?.Host;
|
43
|
+
const {loading, wasLoaded, error, data} = useTypedSelector((state) => state.node);
|
44
|
+
const node = data?.SystemStateInfo?.[0];
|
47
45
|
|
48
46
|
const match =
|
49
47
|
useRouteMatch<{id: string; activeTab: string}>(routes.node) ?? Object.create(null);
|
50
48
|
|
51
49
|
const {id: nodeId, activeTab} = match.params;
|
50
|
+
const {tenantName: tenantNameFromQuery} = parseQuery(location);
|
52
51
|
|
53
52
|
const {activeTabVerified, nodeTabs} = React.useMemo(() => {
|
54
53
|
const hasStorage = _.find(node?.Roles as any[], (el) => el === STORAGE_ROLE);
|
@@ -69,21 +68,16 @@ function Node(props: NodeProps) {
|
|
69
68
|
}, [activeTab, node]);
|
70
69
|
|
71
70
|
React.useEffect(() => {
|
72
|
-
const
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
});
|
83
|
-
}
|
84
|
-
|
85
|
-
dispatch(setHeader(headerItems));
|
86
|
-
}, [dispatch, nodeHost]);
|
71
|
+
const tenantName = node?.Tenants?.[0] || tenantNameFromQuery?.toString();
|
72
|
+
|
73
|
+
dispatch(
|
74
|
+
setHeaderBreadcrumbs('node', {
|
75
|
+
clusterTab: clusterTabsIds.nodes,
|
76
|
+
tenantName,
|
77
|
+
nodeId,
|
78
|
+
}),
|
79
|
+
);
|
80
|
+
}, [dispatch, node, nodeId, tenantNameFromQuery]);
|
87
81
|
|
88
82
|
React.useEffect(() => {
|
89
83
|
const fetchData = () => dispatch(getNodeInfo(nodeId));
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import routes, {createHref} from '../../routes';
|
1
|
+
import routes, {Query, createHref} from '../../routes';
|
2
2
|
|
3
3
|
export const STORAGE = 'storage';
|
4
4
|
export const TABLETS = 'tablets';
|
@@ -21,9 +21,13 @@ export const NODE_PAGES = [
|
|
21
21
|
},
|
22
22
|
];
|
23
23
|
|
24
|
-
export function getDefaultNodePath(nodeId: string | number) {
|
25
|
-
return createHref(
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
export function getDefaultNodePath(nodeId: string | number, query: Query = {}) {
|
25
|
+
return createHref(
|
26
|
+
routes.node,
|
27
|
+
{
|
28
|
+
id: nodeId,
|
29
|
+
activeTab: OVERVIEW,
|
30
|
+
},
|
31
|
+
query,
|
32
|
+
);
|
29
33
|
}
|
@@ -74,8 +74,8 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
|
|
74
74
|
switch (visibleEntities) {
|
75
75
|
case VisibleEntities.All: {
|
76
76
|
return {
|
77
|
-
columnId: TableColumnsIds.
|
78
|
-
order: DataTable.
|
77
|
+
columnId: TableColumnsIds.PoolName,
|
78
|
+
order: DataTable.ASCENDING,
|
79
79
|
};
|
80
80
|
}
|
81
81
|
case VisibleEntities.Missing: {
|
@@ -87,7 +87,7 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
|
|
87
87
|
case VisibleEntities.Space: {
|
88
88
|
return {
|
89
89
|
columnId: TableColumnsIds.UsedSpaceFlag,
|
90
|
-
order: DataTable.
|
90
|
+
order: DataTable.DESCENDING,
|
91
91
|
};
|
92
92
|
}
|
93
93
|
default: {
|
@@ -295,6 +295,14 @@ function StorageGroups({
|
|
295
295
|
|
296
296
|
let columns = allColumns;
|
297
297
|
|
298
|
+
if (visibleEntities === VisibleEntities.All) {
|
299
|
+
columns = allColumns.filter((col) => {
|
300
|
+
return (
|
301
|
+
col.name !== TableColumnsIds.Missing && col.name !== TableColumnsIds.UsedSpaceFlag
|
302
|
+
);
|
303
|
+
});
|
304
|
+
}
|
305
|
+
|
298
306
|
if (visibleEntities === VisibleEntities.Space) {
|
299
307
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
300
308
|
|
@@ -1,16 +1,17 @@
|
|
1
1
|
import {useCallback, useEffect, useRef} from 'react';
|
2
|
-
import {useParams} from 'react-router';
|
2
|
+
import {useLocation, useParams} from 'react-router';
|
3
3
|
import {useDispatch} from 'react-redux';
|
4
4
|
import cn from 'bem-cn-lite';
|
5
5
|
import {Link as ExternalLink} from '@gravity-ui/uikit';
|
6
6
|
|
7
7
|
import {backend} from '../../store';
|
8
|
-
import {getTablet, getTabletDescribe} from '../../store/reducers/tablet';
|
9
|
-
import {
|
10
|
-
import routes, {createHref} from '../../routes';
|
8
|
+
import {getTablet, getTabletDescribe, clearTabletData} from '../../store/reducers/tablet';
|
9
|
+
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
11
10
|
|
12
11
|
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
12
|
+
import {DEVELOPER_UI} from '../../utils/constants';
|
13
13
|
import '../../services/api';
|
14
|
+
import {parseQuery} from '../../routes';
|
14
15
|
|
15
16
|
import EntityStatus from '../../components/EntityStatus/EntityStatus';
|
16
17
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
@@ -19,8 +20,6 @@ import {Icon} from '../../components/Icon';
|
|
19
20
|
import {EmptyState} from '../../components/EmptyState';
|
20
21
|
import {Loader} from '../../components/Loader';
|
21
22
|
|
22
|
-
import {getClusterPath} from '../Cluster/utils';
|
23
|
-
|
24
23
|
import {TabletTable} from './TabletTable';
|
25
24
|
import {TabletInfo} from './TabletInfo';
|
26
25
|
import {TabletControls} from './TabletControls';
|
@@ -35,6 +34,7 @@ export const Tablet = () => {
|
|
35
34
|
const isFirstDataFetchRef = useRef(true);
|
36
35
|
|
37
36
|
const dispatch = useDispatch();
|
37
|
+
const location = useLocation();
|
38
38
|
|
39
39
|
const params = useParams<{id: string}>();
|
40
40
|
const {id} = params;
|
@@ -48,6 +48,25 @@ export const Tablet = () => {
|
|
48
48
|
error,
|
49
49
|
} = useTypedSelector((state) => state.tablet);
|
50
50
|
|
51
|
+
const {
|
52
|
+
nodeId: queryNodeId,
|
53
|
+
type: queryType,
|
54
|
+
state: queryState,
|
55
|
+
tenantName: queryTenantName,
|
56
|
+
} = parseQuery(location);
|
57
|
+
|
58
|
+
const nodeId = tablet.NodeId?.toString() || queryNodeId?.toString();
|
59
|
+
const tabletState = tablet.State || queryState?.toString();
|
60
|
+
const tabletType = tablet.Type || queryType?.toString();
|
61
|
+
const tenantName = tenantPath || queryTenantName?.toString();
|
62
|
+
|
63
|
+
// NOTE: should be reviewed when migrating to React 18
|
64
|
+
useEffect(() => {
|
65
|
+
return () => {
|
66
|
+
dispatch(clearTabletData());
|
67
|
+
};
|
68
|
+
}, [dispatch]);
|
69
|
+
|
51
70
|
useEffect(() => {
|
52
71
|
if (isFirstDataFetchRef.current && tablet && tablet.TenantId) {
|
53
72
|
dispatch(getTabletDescribe(tablet.TenantId));
|
@@ -63,26 +82,15 @@ export const Tablet = () => {
|
|
63
82
|
|
64
83
|
useEffect(() => {
|
65
84
|
dispatch(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
link: createHref(routes.tabletsFilters, undefined, {
|
74
|
-
nodeIds: tablet.NodeId ? [tablet.NodeId] : [],
|
75
|
-
state: tablet.State,
|
76
|
-
type: tablet.Type,
|
77
|
-
tenantPath,
|
78
|
-
}),
|
79
|
-
},
|
80
|
-
{
|
81
|
-
text: tablet.TabletId ?? 'Tablet',
|
82
|
-
},
|
83
|
-
]),
|
85
|
+
setHeaderBreadcrumbs('tablet', {
|
86
|
+
nodeIds: nodeId ? [nodeId] : [],
|
87
|
+
state: tabletState,
|
88
|
+
type: tabletType,
|
89
|
+
tenantName,
|
90
|
+
tabletId: id,
|
91
|
+
}),
|
84
92
|
);
|
85
|
-
}, [dispatch,
|
93
|
+
}, [dispatch, tenantName, id, nodeId, tabletState, tabletType]);
|
86
94
|
|
87
95
|
const renderExternalLinks = (link: {name: string; path: string}, index: number) => {
|
88
96
|
return (
|
@@ -114,7 +122,7 @@ export const Tablet = () => {
|
|
114
122
|
|
115
123
|
const externalLinks = [
|
116
124
|
{
|
117
|
-
name:
|
125
|
+
name: `${DEVELOPER_UI} - tablet`,
|
118
126
|
path: `/tablets?TabletID=${TabletId}`,
|
119
127
|
},
|
120
128
|
];
|
@@ -138,7 +146,7 @@ export const Tablet = () => {
|
|
138
146
|
{Leader && <Tag text="Leader" type="blue" />}
|
139
147
|
<span className={b('loader')}>{loading && <Loader size="s" />}</span>
|
140
148
|
</div>
|
141
|
-
<TabletInfo tablet={tablet} tenantPath={
|
149
|
+
<TabletInfo tablet={tablet} tenantPath={tenantName} />
|
142
150
|
<TabletControls tablet={tablet} fetchData={fetchData} />
|
143
151
|
</div>
|
144
152
|
<div className={b('rigth-pane')}>
|
@@ -12,7 +12,7 @@ import {b} from '../Tablet';
|
|
12
12
|
|
13
13
|
interface TabletInfoProps {
|
14
14
|
tablet: TTabletStateInfo;
|
15
|
-
tenantPath
|
15
|
+
tenantPath?: string;
|
16
16
|
}
|
17
17
|
|
18
18
|
export const TabletInfo = ({tablet, tenantPath}: TabletInfoProps) => {
|
@@ -30,7 +30,7 @@ export const TabletInfo = ({tablet, tenantPath}: TabletInfoProps) => {
|
|
30
30
|
const hasHiveId = HiveId && HiveId !== '0';
|
31
31
|
const hasUptime = State === ETabletState.Active;
|
32
32
|
|
33
|
-
const tabletInfo: InfoViewerItem[] = [{label: 'Database', value: tenantPath}];
|
33
|
+
const tabletInfo: InfoViewerItem[] = [{label: 'Database', value: tenantPath || '-'}];
|
34
34
|
|
35
35
|
if (hasHiveId) {
|
36
36
|
tabletInfo.push({
|
@@ -11,7 +11,7 @@ import ReactList from 'react-list';
|
|
11
11
|
import {Tablet} from '../../components/Tablet';
|
12
12
|
import {AccessDenied} from '../../components/Errors/403';
|
13
13
|
|
14
|
-
import {
|
14
|
+
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
15
15
|
import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
|
16
16
|
import {
|
17
17
|
getTabletsInfo,
|
@@ -22,8 +22,6 @@ import {
|
|
22
22
|
getTablets,
|
23
23
|
} from '../../store/reducers/tabletsFilters';
|
24
24
|
|
25
|
-
import {getClusterPath} from '../Cluster/utils';
|
26
|
-
|
27
25
|
import './TabletsFilters.scss';
|
28
26
|
|
29
27
|
const b = cn('tablets-filters');
|
@@ -76,7 +74,7 @@ class TabletsFilters extends React.Component {
|
|
76
74
|
reloadDescriptor = -1;
|
77
75
|
|
78
76
|
componentDidMount() {
|
79
|
-
const {setStateFilter, setTypeFilter,
|
77
|
+
const {setStateFilter, setTypeFilter, setHeaderBreadcrumbs} = this.props;
|
80
78
|
|
81
79
|
const queryParams = qs.parse(this.props.location.search, {
|
82
80
|
ignoreQueryPrefix: true,
|
@@ -92,15 +90,9 @@ class TabletsFilters extends React.Component {
|
|
92
90
|
this.makeRequest();
|
93
91
|
});
|
94
92
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
link: getClusterPath(),
|
99
|
-
},
|
100
|
-
{
|
101
|
-
text: 'Tablets'
|
102
|
-
}
|
103
|
-
]);
|
93
|
+
setHeaderBreadcrumbs('tablets', {
|
94
|
+
tenantName: path,
|
95
|
+
});
|
104
96
|
}
|
105
97
|
|
106
98
|
componentDidUpdate(prevProps) {
|
@@ -155,7 +147,13 @@ class TabletsFilters extends React.Component {
|
|
155
147
|
const {filteredTablets, size} = this.props;
|
156
148
|
|
157
149
|
return (
|
158
|
-
<Tablet
|
150
|
+
<Tablet
|
151
|
+
tablet={filteredTablets[index]}
|
152
|
+
tenantName={this.state.tenantPath}
|
153
|
+
key={key}
|
154
|
+
size={size}
|
155
|
+
className={b('tablet')}
|
156
|
+
/>
|
159
157
|
);
|
160
158
|
};
|
161
159
|
|
@@ -340,7 +338,7 @@ const mapDispatchToProps = {
|
|
340
338
|
clearWasLoadingFlag,
|
341
339
|
setStateFilter,
|
342
340
|
setTypeFilter,
|
343
|
-
|
341
|
+
setHeaderBreadcrumbs,
|
344
342
|
};
|
345
343
|
|
346
344
|
export default connect(mapStateToProps, mapDispatchToProps)(TabletsFilters);
|
@@ -42,7 +42,7 @@ export const columns: Column<IPreparedConsumerData>[] = [
|
|
42
42
|
<InternalLink
|
43
43
|
to={createHref(routes.tenant, undefined, {
|
44
44
|
...queryParams,
|
45
|
-
[TenantTabsGroups.
|
45
|
+
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.partitions,
|
46
46
|
selectedConsumer: row.name,
|
47
47
|
})}
|
48
48
|
>
|
@@ -3,15 +3,19 @@ $section-title-line-height: 24px;
|
|
3
3
|
|
4
4
|
.kv-detailed-overview {
|
5
5
|
display: flex;
|
6
|
-
gap: 20px;
|
7
6
|
|
7
|
+
width: 100%;
|
8
8
|
height: 100%;
|
9
|
+
gap: 20px;
|
9
10
|
|
10
11
|
&__section {
|
11
12
|
display: flex;
|
12
13
|
overflow-x: hidden;
|
13
14
|
flex: 0 0 calc(50% - 10px);
|
14
15
|
flex-direction: column;
|
16
|
+
|
17
|
+
min-width: 300px;
|
18
|
+
height: max-content;
|
15
19
|
}
|
16
20
|
|
17
21
|
&__modal {
|
@@ -11,9 +11,9 @@ import type {EPathType} from '../../../types/api/schema';
|
|
11
11
|
|
12
12
|
import {useTypedSelector} from '../../../utils/hooks';
|
13
13
|
import routes, {createHref} from '../../../routes';
|
14
|
-
import type {TenantDiagnosticsTab
|
14
|
+
import type {TenantDiagnosticsTab} from '../../../store/reducers/tenant/types';
|
15
15
|
import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema/schema';
|
16
|
-
import {
|
16
|
+
import { setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
|
17
17
|
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
|
18
18
|
|
19
19
|
import {Loader} from '../../../components/Loader';
|
@@ -96,10 +96,6 @@ function Diagnostics(props: DiagnosticsProps) {
|
|
96
96
|
}
|
97
97
|
};
|
98
98
|
|
99
|
-
const forwardToGeneralTab = (tab: TenantGeneralTab) => {
|
100
|
-
dispatch(setTopLevelTab(tab));
|
101
|
-
};
|
102
|
-
|
103
99
|
const renderTabContent = () => {
|
104
100
|
const {type} = props;
|
105
101
|
|
@@ -116,13 +112,7 @@ function Diagnostics(props: DiagnosticsProps) {
|
|
116
112
|
);
|
117
113
|
}
|
118
114
|
case TENANT_DIAGNOSTICS_TABS_IDS.topQueries: {
|
119
|
-
return
|
120
|
-
<TopQueries
|
121
|
-
path={tenantNameString}
|
122
|
-
changeSchemaTab={forwardToGeneralTab}
|
123
|
-
type={type}
|
124
|
-
/>
|
125
|
-
);
|
115
|
+
return <TopQueries path={tenantNameString} type={type} />;
|
126
116
|
}
|
127
117
|
case TENANT_DIAGNOSTICS_TABS_IDS.topShards: {
|
128
118
|
return <TopShards tenantPath={tenantNameString} type={type} />;
|
@@ -176,7 +166,7 @@ function Diagnostics(props: DiagnosticsProps) {
|
|
176
166
|
wrapTo={({id}, node) => {
|
177
167
|
const path = createHref(routes.tenant, undefined, {
|
178
168
|
...queryParams,
|
179
|
-
[TenantTabsGroups.
|
169
|
+
[TenantTabsGroups.diagnosticsTab]: id,
|
180
170
|
});
|
181
171
|
|
182
172
|
return (
|
@@ -3,9 +3,11 @@
|
|
3
3
|
@import '@gravity-ui/uikit/styles/mixins.scss';
|
4
4
|
|
5
5
|
.healthcheck {
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
&_expanded {
|
7
|
+
// Since most of the inner containers have fixed width, we can set fixed width here as well
|
8
|
+
// Thus we will get rid of unneeded layout shift when scrollbar appear
|
9
|
+
min-width: 885px;
|
10
|
+
}
|
9
11
|
|
10
12
|
&__details {
|
11
13
|
padding: 25px 20px 20px;
|
@@ -99,5 +99,5 @@ export const Healthcheck = (props: HealthcheckProps) => {
|
|
99
99
|
return <div className="error">{i18n('no-data')}</div>;
|
100
100
|
};
|
101
101
|
|
102
|
-
return <div className={b()}>{renderContent()}</div>;
|
102
|
+
return <div className={b({expanded: !preview})}>{renderContent()}</div>;
|
103
103
|
};
|
@@ -105,6 +105,7 @@ class TenantOverview extends React.Component {
|
|
105
105
|
PoolStats,
|
106
106
|
StateStats = [],
|
107
107
|
MemoryUsed,
|
108
|
+
Name,
|
108
109
|
CoresUsed,
|
109
110
|
StorageGroups,
|
110
111
|
StorageAllocatedSize,
|
@@ -159,7 +160,7 @@ class TenantOverview extends React.Component {
|
|
159
160
|
<div className={b('system-tablets')}>
|
160
161
|
{SystemTablets &&
|
161
162
|
SystemTablets.map((tablet, tabletIndex) => (
|
162
|
-
<Tablet key={tabletIndex} tablet={tablet} />
|
163
|
+
<Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
|
163
164
|
))}
|
164
165
|
</div>
|
165
166
|
<div className={b('common-info')}>
|