ydb-embedded-ui 4.5.2 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/assets/icons/versions.svg +3 -0
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +7 -2
  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 +8 -4
  7. package/dist/containers/AsideNavigation/AsideNavigation.tsx +4 -50
  8. package/dist/containers/Cluster/Cluster.scss +7 -48
  9. package/dist/containers/Cluster/Cluster.tsx +129 -20
  10. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +34 -17
  11. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +58 -92
  12. package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.scss +48 -0
  13. package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +34 -0
  14. package/dist/containers/Cluster/utils.tsx +45 -0
  15. package/dist/containers/Header/Header.scss +4 -19
  16. package/dist/containers/Header/Header.tsx +72 -46
  17. package/dist/containers/Header/breadcrumbs.ts +146 -0
  18. package/dist/containers/Node/Node.tsx +25 -29
  19. package/dist/containers/Node/NodePages.ts +10 -6
  20. package/dist/containers/Nodes/Nodes.tsx +0 -16
  21. package/dist/containers/Nodes/getNodesColumns.tsx +1 -1
  22. package/dist/containers/Storage/Storage.js +1 -11
  23. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  24. package/dist/containers/Tablet/Tablet.tsx +40 -4
  25. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  26. package/dist/containers/TabletsFilters/TabletsFilters.js +15 -2
  27. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  28. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +1 -1
  29. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +7 -0
  30. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -4
  31. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  32. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  33. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +4 -6
  34. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +56 -53
  35. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  36. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +11 -13
  37. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
  38. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -2
  39. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
  40. package/dist/containers/Tenant/Preview/Preview.js +1 -1
  41. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  42. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  43. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  44. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  45. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  46. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  47. package/dist/containers/Tenant/Query/Query.scss +16 -0
  48. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  49. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +43 -100
  50. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  51. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +10 -3
  52. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  53. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +8 -1
  54. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +1 -6
  55. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  56. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  57. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  58. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  59. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  60. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  61. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  62. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -1
  63. package/dist/containers/Tenant/Tenant.tsx +4 -25
  64. package/dist/containers/Tenant/TenantPages.tsx +8 -2
  65. package/dist/containers/Tenant/utils/constants.ts +10 -0
  66. package/dist/containers/Tenant/utils/schemaActions.ts +8 -3
  67. package/dist/containers/Tenants/Tenants.js +39 -37
  68. package/dist/containers/Tenants/Tenants.scss +2 -4
  69. package/dist/containers/UserSettings/i18n/en.json +2 -2
  70. package/dist/containers/UserSettings/i18n/ru.json +2 -2
  71. package/dist/containers/UserSettings/settings.ts +4 -4
  72. package/dist/containers/Versions/Versions.scss +0 -4
  73. package/dist/containers/Versions/Versions.tsx +74 -66
  74. package/dist/routes.ts +8 -6
  75. package/dist/services/api.ts +15 -7
  76. package/dist/store/reducers/clusterNodes/clusterNodes.tsx +4 -0
  77. package/dist/store/reducers/executeQuery.ts +1 -1
  78. package/dist/store/reducers/header/header.ts +31 -0
  79. package/dist/store/reducers/header/types.ts +54 -0
  80. package/dist/store/reducers/index.ts +4 -2
  81. package/dist/store/reducers/node/types.ts +2 -0
  82. package/dist/store/reducers/overview/overview.ts +109 -0
  83. package/dist/store/reducers/overview/types.ts +24 -0
  84. package/dist/store/reducers/{schema.ts → schema/schema.ts} +24 -50
  85. package/dist/{types/store/schema.ts → store/reducers/schema/types.ts} +16 -15
  86. package/dist/store/reducers/settings/settings.ts +5 -3
  87. package/dist/store/reducers/tablet.ts +18 -1
  88. package/dist/store/reducers/tenant/constants.ts +6 -0
  89. package/dist/store/reducers/tenant/tenant.ts +21 -2
  90. package/dist/store/reducers/tenant/types.ts +9 -2
  91. package/dist/store/reducers/topic.ts +1 -1
  92. package/dist/store/state-url-mapping.js +4 -1
  93. package/dist/types/api/query.ts +78 -44
  94. package/dist/types/store/explainQuery.ts +2 -2
  95. package/dist/types/store/query.ts +9 -2
  96. package/dist/types/store/tablet.ts +7 -4
  97. package/dist/utils/constants.ts +5 -1
  98. package/dist/utils/nodes.ts +1 -1
  99. package/dist/utils/query.ts +3 -3
  100. package/package.json +2 -1
  101. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  102. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  103. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  104. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  105. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  106. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  107. package/dist/store/reducers/header.ts +0 -26
  108. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  109. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  110. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  111. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  112. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  113. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  114. /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -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,9 +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, {CLUSTER_PAGES, createHref} from '../../routes';
20
- import {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 {useTypedSelector} from '../../utils/hooks';
23
+
24
+ import {clusterTabsIds} from '../Cluster/utils';
22
25
 
23
26
  import './Node.scss';
24
27
 
@@ -26,11 +29,6 @@ const b = cn('node');
26
29
 
27
30
  export const STORAGE_ROLE = 'Storage';
28
31
 
29
- const headerNodes = {
30
- text: CLUSTER_PAGES.nodes.title,
31
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.nodes.id}),
32
- };
33
-
34
32
  const autofetcher = new AutoFetcher();
35
33
 
36
34
  interface NodeProps {
@@ -40,19 +38,16 @@ interface NodeProps {
40
38
 
41
39
  function Node(props: NodeProps) {
42
40
  const dispatch = useDispatch();
41
+ const location = useLocation();
43
42
 
44
- const wasLoaded = useSelector((state: any) => state.node.wasLoaded);
45
- const loading = useSelector((state: any) => state.node.loading);
46
- const error = useSelector((state: any) => state.node.error);
47
-
48
- const node = useSelector((state: any) => state.node?.data?.SystemStateInfo?.[0]);
49
-
50
- const nodeHost = node?.Host;
43
+ const {loading, wasLoaded, error, data} = useTypedSelector((state) => state.node);
44
+ const node = data?.SystemStateInfo?.[0];
51
45
 
52
46
  const match =
53
47
  useRouteMatch<{id: string; activeTab: string}>(routes.node) ?? Object.create(null);
54
48
 
55
49
  const {id: nodeId, activeTab} = match.params;
50
+ const {tenantName: tenantNameFromQuery} = parseQuery(location);
56
51
 
57
52
  const {activeTabVerified, nodeTabs} = React.useMemo(() => {
58
53
  const hasStorage = _.find(node?.Roles as any[], (el) => el === STORAGE_ROLE);
@@ -72,28 +67,29 @@ function Node(props: NodeProps) {
72
67
  return {activeTabVerified, nodeTabs};
73
68
  }, [activeTab, node]);
74
69
 
70
+ React.useEffect(() => {
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]);
81
+
75
82
  React.useEffect(() => {
76
83
  const fetchData = () => dispatch(getNodeInfo(nodeId));
77
84
  fetchData();
78
85
  autofetcher.start();
79
86
  autofetcher.fetch(() => fetchData());
80
- dispatch(setHeader([headerNodes]));
87
+
81
88
  return () => {
82
89
  autofetcher.stop();
83
90
  dispatch(resetNode());
84
91
  };
85
- }, [nodeId]);
86
-
87
- React.useEffect(() => {
88
- dispatch(
89
- setHeader([
90
- headerNodes,
91
- {
92
- text: nodeHost,
93
- },
94
- ]),
95
- );
96
- }, [nodeHost]);
92
+ }, [dispatch, nodeId]);
97
93
 
98
94
  const renderTabs = () => {
99
95
  return (
@@ -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
  }
@@ -15,13 +15,10 @@ import {ProblemFilter} from '../../components/ProblemFilter';
15
15
  import {UptimeFilter} from '../../components/UptimeFIlter';
16
16
  import {EntitiesCount} from '../../components/EntitiesCount';
17
17
 
18
- import routes, {CLUSTER_PAGES, createHref} from '../../routes';
19
-
20
18
  import {DEFAULT_TABLE_SETTINGS, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY} from '../../utils/constants';
21
19
  import {useAutofetcher, useSetting, useTypedSelector} from '../../utils/hooks';
22
20
  import {AdditionalNodesInfo, isUnavailableNode, NodesUptimeFilterValues} from '../../utils/nodes';
23
21
 
24
- import {setHeader} from '../../store/reducers/header';
25
22
  import {
26
23
  getNodes,
27
24
  getFilteredPreparedNodesList,
@@ -82,19 +79,6 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
82
79
 
83
80
  useAutofetcher(fetchNodes, [fetchNodes], isClusterNodes ? true : autorefresh);
84
81
 
85
- useEffect(() => {
86
- if (isClusterNodes) {
87
- dispatch(
88
- setHeader([
89
- {
90
- text: CLUSTER_PAGES.nodes.title,
91
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.nodes.id}),
92
- },
93
- ]),
94
- );
95
- }
96
- }, [dispatch, isClusterNodes]);
97
-
98
82
  const handleSearchQueryChange = (value: string) => {
99
83
  dispatch(setSearchValue(value));
100
84
  };
@@ -13,7 +13,7 @@ import type {INodesPreparedEntity} from '../../types/store/nodes';
13
13
 
14
14
  interface GetNodesColumnsProps {
15
15
  tabletsPath?: string;
16
- getNodeRef?: (node?: NodeAddress) => string;
16
+ getNodeRef?: (node?: NodeAddress) => string | null;
17
17
  }
18
18
 
19
19
  export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps) {
@@ -35,8 +35,6 @@ import {getNodesList, selectNodesMap} from '../../store/reducers/nodesList';
35
35
  import StorageGroups from './StorageGroups/StorageGroups';
36
36
  import StorageNodes from './StorageNodes/StorageNodes';
37
37
  import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
38
- import {setHeader} from '../../store/reducers/header';
39
- import routes, {CLUSTER_PAGES, createHref} from '../../routes';
40
38
 
41
39
  import './Storage.scss';
42
40
 
@@ -67,7 +65,6 @@ class Storage extends React.Component {
67
65
  setStorageFilter: PropTypes.func,
68
66
  setVisibleEntities: PropTypes.func,
69
67
  visibleEntities: PropTypes.string,
70
- setHeader: PropTypes.func,
71
68
  tenant: PropTypes.string,
72
69
  nodeId: PropTypes.string,
73
70
  nodesUptimeFilter: PropTypes.string,
@@ -77,7 +74,7 @@ class Storage extends React.Component {
77
74
  };
78
75
 
79
76
  componentDidMount() {
80
- const {tenant, nodeId, setVisibleEntities, storageType, setHeader, getNodesList} =
77
+ const {tenant, nodeId, setVisibleEntities, storageType, getNodesList} =
81
78
  this.props;
82
79
 
83
80
  this.autofetcher = new AutoFetcher();
@@ -89,12 +86,6 @@ class Storage extends React.Component {
89
86
  type: storageType,
90
87
  });
91
88
  } else {
92
- setHeader([
93
- {
94
- text: CLUSTER_PAGES.storage.title,
95
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.storage.id}),
96
- },
97
- ]);
98
89
  this.getStorageInfo({
99
90
  filter: FILTER_OPTIONS.Missing,
100
91
  type: storageType,
@@ -375,7 +366,6 @@ const mapDispatchToProps = {
375
366
  setNodesUptimeFilter,
376
367
  getNodesList,
377
368
  setStorageType,
378
- setHeader,
379
369
  setDataWasNotLoaded,
380
370
  };
381
371
 
@@ -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,13 +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';
8
+ import {getTablet, getTabletDescribe, clearTabletData} from '../../store/reducers/tablet';
9
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
10
+
9
11
  import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
12
+ import {DEVELOPER_UI} from '../../utils/constants';
10
13
  import '../../services/api';
14
+ import {parseQuery} from '../../routes';
11
15
 
12
16
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
13
17
  import {ResponseError} from '../../components/Errors/ResponseError';
@@ -30,6 +34,7 @@ export const Tablet = () => {
30
34
  const isFirstDataFetchRef = useRef(true);
31
35
 
32
36
  const dispatch = useDispatch();
37
+ const location = useLocation();
33
38
 
34
39
  const params = useParams<{id: string}>();
35
40
  const {id} = params;
@@ -43,6 +48,25 @@ export const Tablet = () => {
43
48
  error,
44
49
  } = useTypedSelector((state) => state.tablet);
45
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
+
46
70
  useEffect(() => {
47
71
  if (isFirstDataFetchRef.current && tablet && tablet.TenantId) {
48
72
  dispatch(getTabletDescribe(tablet.TenantId));
@@ -56,6 +80,18 @@ export const Tablet = () => {
56
80
 
57
81
  useAutofetcher(fetchData, [fetchData], true);
58
82
 
83
+ useEffect(() => {
84
+ dispatch(
85
+ setHeaderBreadcrumbs('tablet', {
86
+ nodeIds: nodeId ? [nodeId] : [],
87
+ state: tabletState,
88
+ type: tabletType,
89
+ tenantName,
90
+ tabletId: id,
91
+ }),
92
+ );
93
+ }, [dispatch, tenantName, id, nodeId, tabletState, tabletType]);
94
+
59
95
  const renderExternalLinks = (link: {name: string; path: string}, index: number) => {
60
96
  return (
61
97
  <li key={index} className={b('link', {external: true})}>
@@ -86,7 +122,7 @@ export const Tablet = () => {
86
122
 
87
123
  const externalLinks = [
88
124
  {
89
- name: 'Internal viewer - tablet',
125
+ name: `${DEVELOPER_UI} - tablet`,
90
126
  path: `/tablets?TabletID=${TabletId}`,
91
127
  },
92
128
  ];
@@ -110,7 +146,7 @@ export const Tablet = () => {
110
146
  {Leader && <Tag text="Leader" type="blue" />}
111
147
  <span className={b('loader')}>{loading && <Loader size="s" />}</span>
112
148
  </div>
113
- <TabletInfo tablet={tablet} tenantPath={tenantPath} />
149
+ <TabletInfo tablet={tablet} tenantPath={tenantName} />
114
150
  <TabletControls tablet={tablet} fetchData={fetchData} />
115
151
  </div>
116
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,6 +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 {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
14
15
  import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
15
16
  import {
16
17
  getTabletsInfo,
@@ -41,6 +42,7 @@ class TabletsFilters extends React.Component {
41
42
  stateFilter: PropTypes.array,
42
43
  typeFilter: PropTypes.array,
43
44
  error: PropTypes.oneOf([PropTypes.string, PropTypes.object]),
45
+ setHeader: PropTypes.func,
44
46
  };
45
47
 
46
48
  static renderLoader() {
@@ -72,7 +74,7 @@ class TabletsFilters extends React.Component {
72
74
  reloadDescriptor = -1;
73
75
 
74
76
  componentDidMount() {
75
- const {setStateFilter, setTypeFilter} = this.props;
77
+ const {setStateFilter, setTypeFilter, setHeaderBreadcrumbs} = this.props;
76
78
 
77
79
  const queryParams = qs.parse(this.props.location.search, {
78
80
  ignoreQueryPrefix: true,
@@ -87,6 +89,10 @@ class TabletsFilters extends React.Component {
87
89
  this.setState({nodeFilter: nodes, tenantPath: path}, () => {
88
90
  this.makeRequest();
89
91
  });
92
+
93
+ setHeaderBreadcrumbs('tablets', {
94
+ tenantName: path,
95
+ });
90
96
  }
91
97
 
92
98
  componentDidUpdate(prevProps) {
@@ -141,7 +147,13 @@ class TabletsFilters extends React.Component {
141
147
  const {filteredTablets, size} = this.props;
142
148
 
143
149
  return (
144
- <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
+ />
145
157
  );
146
158
  };
147
159
 
@@ -326,6 +338,7 @@ const mapDispatchToProps = {
326
338
  clearWasLoadingFlag,
327
339
  setStateFilter,
328
340
  setTypeFilter,
341
+ setHeaderBreadcrumbs,
329
342
  };
330
343
 
331
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
  >
@@ -15,7 +15,7 @@ import {
15
15
  setCurrentDescribePath,
16
16
  getDescribeBatched,
17
17
  } from '../../../../store/reducers/describe';
18
- import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema';
18
+ import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema';
19
19
  import type {EPathType} from '../../../../types/api/schema';
20
20
 
21
21
  import {isEntityWithMergedImplementation} from '../../utils/schema';
@@ -3,12 +3,19 @@ $section-title-line-height: 24px;
3
3
 
4
4
  .kv-detailed-overview {
5
5
  display: flex;
6
+
7
+ width: 100%;
8
+ height: 100%;
6
9
  gap: 20px;
10
+
7
11
  &__section {
8
12
  display: flex;
9
13
  overflow-x: hidden;
10
14
  flex: 0 0 calc(50% - 10px);
11
15
  flex-direction: column;
16
+
17
+ min-width: 300px;
18
+ height: max-content;
12
19
  }
13
20
 
14
21
  &__modal {
@@ -12,7 +12,7 @@ import type {EPathType} from '../../../types/api/schema';
12
12
  import {useTypedSelector} from '../../../utils/hooks';
13
13
  import routes, {createHref} from '../../../routes';
14
14
  import type {TenantDiagnosticsTab, TenantGeneralTab} from '../../../store/reducers/tenant/types';
15
- import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema';
15
+ import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema/schema';
16
16
  import {setTopLevelTab, setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
17
17
  import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
18
18
 
@@ -49,8 +49,8 @@ const b = cn('kv-tenant-diagnostics');
49
49
 
50
50
  function Diagnostics(props: DiagnosticsProps) {
51
51
  const dispatch = useDispatch();
52
- const {currentSchemaPath, autorefresh} = useSelector((state: any) => state.schema);
53
- const {diagnosticsTab = TENANT_DIAGNOSTICS_TABS_IDS.overview, wasLoaded} = useTypedSelector(
52
+ const {currentSchemaPath, autorefresh, wasLoaded} = useSelector((state: any) => state.schema);
53
+ const {diagnosticsTab = TENANT_DIAGNOSTICS_TABS_IDS.overview} = useTypedSelector(
54
54
  (state) => state.tenant,
55
55
  );
56
56
 
@@ -176,7 +176,7 @@ function Diagnostics(props: DiagnosticsProps) {
176
176
  wrapTo={({id}, node) => {
177
177
  const path = createHref(routes.tenant, undefined, {
178
178
  ...queryParams,
179
- [TenantTabsGroups.generalTab]: id,
179
+ [TenantTabsGroups.diagnosticsTab]: id,
180
180
  });
181
181
 
182
182
  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
  };
@@ -7,7 +7,6 @@ import {
7
7
  } from '../../../../../components/InfoViewer/formatters';
8
8
 
9
9
  import {useTypedSelector} from '../../../../../utils/hooks';
10
- import {selectSchemaData} from '../../../../../store/reducers/schema';
11
10
 
12
11
  import {getEntityName} from '../../../utils';
13
12
 
@@ -42,27 +41,26 @@ const prepareChangefeedInfo = (
42
41
 
43
42
  interface ChangefeedProps {
44
43
  data?: TEvDescribeSchemeResult;
45
- childrenPaths?: string[];
44
+ topic?: TEvDescribeSchemeResult;
46
45
  }
47
46
 
48
47
  /** Displays overview for CDCStream EPathType */
49
- export const ChangefeedInfo = ({data, childrenPaths}: ChangefeedProps) => {
48
+ export const ChangefeedInfo = ({data, topic}: ChangefeedProps) => {
50
49
  const entityName = getEntityName(data?.PathDescription);
51
50
 
52
51
  const {error: schemaError} = useTypedSelector((state) => state.schema);
53
- const pqGroupData = useTypedSelector((state) => selectSchemaData(state, childrenPaths?.[0]));
54
52
 
55
53
  if (schemaError) {
56
54
  return <div className="error">{schemaError.statusText}</div>;
57
55
  }
58
56
 
59
- if (!data || !pqGroupData) {
57
+ if (!data || !topic) {
60
58
  return <div className="error">No {entityName} data</div>;
61
59
  }
62
60
 
63
61
  return (
64
62
  <div>
65
- <InfoViewer title={entityName} info={prepareChangefeedInfo(data, pqGroupData)} />
63
+ <InfoViewer title={entityName} info={prepareChangefeedInfo(data, topic)} />
66
64
  <TopicStats />
67
65
  </div>
68
66
  );