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.
Files changed (90) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/assets/icons/versions.svg +3 -0
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +6 -1
  4. package/dist/components/Tablet/Tablet.tsx +17 -3
  5. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +23 -16
  6. package/dist/containers/App/Content.js +5 -2
  7. package/dist/containers/AsideNavigation/AsideNavigation.tsx +50 -18
  8. package/dist/containers/Cluster/Cluster.tsx +6 -13
  9. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +3 -3
  10. package/dist/containers/Cluster/{utils.ts → utils.tsx} +11 -0
  11. package/dist/containers/Header/Header.scss +9 -0
  12. package/dist/containers/Header/Header.tsx +70 -14
  13. package/dist/containers/Header/breadcrumbs.ts +146 -0
  14. package/dist/containers/Node/Node.tsx +21 -27
  15. package/dist/containers/Node/NodePages.ts +10 -6
  16. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  17. package/dist/containers/Tablet/Tablet.tsx +35 -27
  18. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  19. package/dist/containers/TabletsFilters/TabletsFilters.js +13 -15
  20. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  21. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +5 -1
  22. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -14
  23. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  24. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  26. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +9 -16
  27. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +11 -11
  28. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
  29. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  30. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  31. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  32. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  33. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  34. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  35. package/dist/containers/Tenant/Query/Query.scss +16 -0
  36. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  37. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +39 -88
  38. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  39. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  40. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  41. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  42. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  43. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  44. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  45. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  46. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  47. package/dist/containers/Tenant/Tenant.scss +0 -8
  48. package/dist/containers/Tenant/Tenant.tsx +24 -46
  49. package/dist/containers/Tenant/TenantPages.tsx +7 -16
  50. package/dist/containers/Tenant/utils/constants.ts +10 -0
  51. package/dist/containers/Tenant/utils/schemaActions.ts +9 -4
  52. package/dist/containers/Tenants/Tenants.js +26 -13
  53. package/dist/routes.ts +21 -7
  54. package/dist/services/api.ts +9 -5
  55. package/dist/store/reducers/executeQuery.ts +18 -4
  56. package/dist/store/reducers/header/header.ts +31 -0
  57. package/dist/store/reducers/header/types.ts +54 -0
  58. package/dist/store/reducers/index.ts +1 -1
  59. package/dist/store/reducers/node/types.ts +2 -0
  60. package/dist/store/reducers/settings/settings.ts +8 -3
  61. package/dist/store/reducers/tablet.ts +18 -1
  62. package/dist/store/reducers/tenant/constants.ts +9 -1
  63. package/dist/store/reducers/tenant/tenant.ts +23 -4
  64. package/dist/store/reducers/tenant/types.ts +9 -5
  65. package/dist/store/reducers/topic.ts +1 -1
  66. package/dist/store/state-url-mapping.js +6 -3
  67. package/dist/types/store/executeQuery.ts +4 -1
  68. package/dist/types/store/query.ts +5 -0
  69. package/dist/types/store/tablet.ts +7 -4
  70. package/dist/utils/constants.ts +5 -1
  71. package/package.json +2 -1
  72. package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.scss +0 -9
  73. package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.tsx +0 -68
  74. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  75. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  76. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  77. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  78. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  79. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  80. package/dist/store/reducers/header.ts +0 -26
  81. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  82. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  83. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  84. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  85. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  86. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +0 -0
  87. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +0 -0
  88. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +0 -0
  89. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  90. /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, useSelector} from 'react-redux';
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 {HeaderItemType, setHeader} from '../../store/reducers/header';
19
+ import routes, {createHref, parseQuery} from '../../routes';
20
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
21
21
  import {AutoFetcher} from '../../utils/autofetcher';
22
- import {clusterTabsIds, getClusterPath} from '../Cluster/utils';
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 = useSelector((state: any) => state.node.wasLoaded);
41
- const loading = useSelector((state: any) => state.node.loading);
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 headerItems: HeaderItemType[] = [
73
- {
74
- text: 'Cluster',
75
- link: getClusterPath(clusterTabsIds.nodes),
76
- },
77
- ];
78
-
79
- if (nodeHost) {
80
- headerItems.push({
81
- text: nodeHost,
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(routes.node, {
26
- id: nodeId,
27
- activeTab: OVERVIEW,
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.Missing,
78
- order: DataTable.DESCENDING,
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.ASCENDING,
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 {setHeader} from '../../store/reducers/header';
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
- setHeader([
67
- {
68
- text: 'Cluster',
69
- link: getClusterPath(),
70
- },
71
- {
72
- text: 'Tablets',
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, tenantPath, tablet]);
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: 'Internal viewer - tablet',
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={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: string;
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 {setHeader} from '../../store/reducers/header';
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, setHeader} = this.props;
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
- setHeader([
96
- {
97
- text: 'Cluster',
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 tablet={filteredTablets[index]} key={key} size={size} className={b('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
- setHeader,
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.generalTab]: TENANT_DIAGNOSTICS_TABS_IDS.partitions,
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, TenantGeneralTab} from '../../../store/reducers/tenant/types';
14
+ import type {TenantDiagnosticsTab} from '../../../store/reducers/tenant/types';
15
15
  import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema/schema';
16
- import {setTopLevelTab, setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
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.generalTab]: id,
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
- // Since most of the inner containers have fixed width, we can set fixed width here as well
7
- // Thus we will get rid of unneeded layout shift when scrollbar appear
8
- min-width: 885px;
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')}>