ydb-embedded-ui 4.4.2 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/ContentWithPopup/ContentWithPopup.tsx +51 -0
  3. package/dist/components/CriticalActionDialog/CriticalActionDialog.tsx +3 -0
  4. package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.scss +7 -0
  5. package/dist/components/ExternalLinkWithIcon/ExternalLinkWithIcon.tsx +24 -0
  6. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
  7. package/dist/components/PoolBar/PoolBar.scss +6 -1
  8. package/dist/components/PoolBar/PoolBar.tsx +39 -0
  9. package/dist/components/PoolsGraph/PoolsGraph.scss +1 -1
  10. package/dist/components/PoolsGraph/PoolsGraph.tsx +23 -0
  11. package/dist/components/Tablet/Tablet.scss +4 -1
  12. package/dist/components/Tablet/Tablet.tsx +11 -35
  13. package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.scss} +1 -1
  14. package/dist/components/{Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx → TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.tsx} +3 -3
  15. package/dist/components/TooltipsContent/PoolTooltipContent/PoolTooltipContent.tsx +24 -0
  16. package/dist/components/TooltipsContent/TabletTooltipContent/TabletTooltipContent.tsx +34 -0
  17. package/dist/components/TooltipsContent/index.ts +3 -0
  18. package/dist/containers/Cluster/Cluster.tsx +14 -10
  19. package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/ClusterInfo.scss +8 -40
  20. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +223 -0
  21. package/dist/containers/{ClusterInfo → Cluster/ClusterInfo}/utils.ts +1 -1
  22. package/dist/containers/Cluster/VersionsBar/VersionsBar.scss +27 -0
  23. package/dist/containers/Cluster/VersionsBar/VersionsBar.tsx +33 -0
  24. package/dist/containers/Header/Header.tsx +3 -6
  25. package/dist/containers/Nodes/Nodes.tsx +0 -11
  26. package/dist/containers/Nodes/getNodesColumns.tsx +3 -20
  27. package/dist/containers/Tablet/Tablet.scss +4 -0
  28. package/dist/containers/Tablet/Tablet.tsx +2 -1
  29. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +19 -27
  30. package/dist/containers/Tablets/Tablets.tsx +1 -17
  31. package/dist/containers/TabletsFilters/TabletsFilters.js +2 -14
  32. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +2 -2
  33. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +37 -38
  34. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +15 -28
  35. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +4 -14
  36. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +5 -3
  37. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -3
  38. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +3 -3
  39. package/dist/containers/Tenant/Tenant.tsx +14 -15
  40. package/dist/containers/Tenant/TenantPages.tsx +3 -6
  41. package/dist/containers/Tenant/utils/schemaActions.ts +4 -4
  42. package/dist/containers/Tenants/Tenants.js +3 -17
  43. package/dist/containers/Versions/NodesTable/NodesTable.tsx +4 -34
  44. package/dist/routes.ts +1 -1
  45. package/dist/store/reducers/index.ts +1 -1
  46. package/dist/store/reducers/tenant/constants.ts +19 -0
  47. package/dist/store/reducers/{tenant.js → tenant/tenant.ts} +27 -36
  48. package/dist/store/reducers/tenant/types.ts +25 -0
  49. package/dist/types/additionalProps.ts +11 -0
  50. package/dist/utils/index.js +2 -1
  51. package/dist/utils/tooltip.js +8 -80
  52. package/package.json +2 -1
  53. package/dist/components/Breadcrumbs/Breadcrumbs.js +0 -25
  54. package/dist/components/Breadcrumbs/Breadcrumbs.scss +0 -5
  55. package/dist/components/Collapse/Collapse.js +0 -84
  56. package/dist/components/Collapse/Collapse.scss +0 -70
  57. package/dist/components/PoolBar/PoolBar.js +0 -52
  58. package/dist/components/PoolsGraph/PoolsGraph.js +0 -33
  59. package/dist/containers/ClusterInfo/ClusterInfo.tsx +0 -207
@@ -0,0 +1,223 @@
1
+ import {useCallback, useEffect, useMemo} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import {useLocation} from 'react-router';
4
+ import block from 'bem-cn-lite';
5
+ import qs from 'qs';
6
+
7
+ import EntityStatus from '../../../components/EntityStatus/EntityStatus';
8
+ import ProgressViewer from '../../../components/ProgressViewer/ProgressViewer';
9
+ import InfoViewer, {InfoViewerItem} from '../../../components/InfoViewer/InfoViewer';
10
+ import {Tags} from '../../../components/Tags';
11
+ import {Tablet} from '../../../components/Tablet';
12
+ import {Loader} from '../../../components/Loader';
13
+ import {ResponseError} from '../../../components/Errors/ResponseError';
14
+ import {ExternalLinkWithIcon} from '../../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
15
+
16
+ import type {
17
+ AdditionalClusterProps,
18
+ AdditionalVersionsProps,
19
+ ClusterLink,
20
+ } from '../../../types/additionalProps';
21
+ import type {VersionValue} from '../../../types/versions';
22
+ import type {TClusterInfo} from '../../../types/api/cluster';
23
+ import {getClusterNodes} from '../../../store/reducers/clusterNodes/clusterNodes';
24
+ import {getClusterInfo} from '../../../store/reducers/cluster/cluster';
25
+ import {backend, customBackend} from '../../../store';
26
+ import {setHeader} from '../../../store/reducers/header';
27
+ import {formatStorageValues} from '../../../utils';
28
+ import {useAutofetcher, useTypedSelector} from '../../../utils/hooks';
29
+ import {
30
+ parseVersionsToVersionToColorMap,
31
+ parseNodesToVersionsValues,
32
+ } from '../../../utils/versions';
33
+ import routes, {CLUSTER_PAGES, createHref} from '../../../routes';
34
+
35
+ import {Versions} from '../../Versions/Versions';
36
+ import {VersionsBar} from '../VersionsBar/VersionsBar';
37
+
38
+ import {compareTablets} from './utils';
39
+
40
+ import './ClusterInfo.scss';
41
+
42
+ const b = block('cluster-info');
43
+
44
+ const getInfo = (
45
+ cluster: TClusterInfo,
46
+ versionsValues: VersionValue[],
47
+ additionalInfo: InfoViewerItem[],
48
+ links: ClusterLink[],
49
+ ) => {
50
+ const info: InfoViewerItem[] = [];
51
+
52
+ if (cluster.DataCenters) {
53
+ info.push({
54
+ label: 'DC',
55
+ value: <Tags tags={cluster.DataCenters} />,
56
+ });
57
+ }
58
+
59
+ if (cluster.SystemTablets) {
60
+ info.push({
61
+ label: 'Tablets',
62
+ value: (
63
+ <div className={b('system-tablets')}>
64
+ {cluster.SystemTablets.sort(compareTablets).map((tablet, tabletIndex) => (
65
+ <Tablet key={tabletIndex} tablet={tablet} />
66
+ ))}
67
+ </div>
68
+ ),
69
+ });
70
+ }
71
+
72
+ info.push(
73
+ {
74
+ label: 'Nodes',
75
+ value: (
76
+ <ProgressViewer
77
+ className={b('metric-field')}
78
+ value={cluster?.NodesAlive}
79
+ capacity={cluster?.NodesTotal}
80
+ />
81
+ ),
82
+ },
83
+ {
84
+ label: 'Load',
85
+ value: (
86
+ <ProgressViewer
87
+ className={b('metric-field')}
88
+ value={cluster?.LoadAverage}
89
+ capacity={cluster?.NumberOfCpus}
90
+ />
91
+ ),
92
+ },
93
+ {
94
+ label: 'Storage',
95
+ value: (
96
+ <ProgressViewer
97
+ className={b('metric-field')}
98
+ value={cluster?.StorageUsed}
99
+ capacity={cluster?.StorageTotal}
100
+ formatValues={formatStorageValues}
101
+ />
102
+ ),
103
+ },
104
+ ...additionalInfo,
105
+ {
106
+ label: 'Links',
107
+ value: (
108
+ <div className={b('links')}>
109
+ {links.map(({title, url}) => (
110
+ <ExternalLinkWithIcon key={title} title={title} url={url} />
111
+ ))}
112
+ </div>
113
+ ),
114
+ },
115
+ {
116
+ label: 'Versions',
117
+ value: <VersionsBar versionsValues={versionsValues} />,
118
+ },
119
+ );
120
+
121
+ return info;
122
+ };
123
+
124
+ interface ClusterInfoProps {
125
+ clusterTitle?: string;
126
+ additionalClusterProps?: AdditionalClusterProps;
127
+ additionalVersionsProps?: AdditionalVersionsProps;
128
+ }
129
+
130
+ export const ClusterInfo = ({
131
+ clusterTitle,
132
+ additionalClusterProps = {},
133
+ additionalVersionsProps = {},
134
+ }: ClusterInfoProps) => {
135
+ const dispatch = useDispatch();
136
+ const location = useLocation();
137
+
138
+ const queryParams = qs.parse(location.search, {
139
+ ignoreQueryPrefix: true,
140
+ });
141
+ const {clusterName} = queryParams;
142
+
143
+ const {
144
+ data: cluster = {},
145
+ loading,
146
+ wasLoaded,
147
+ error,
148
+ } = useTypedSelector((state) => state.cluster);
149
+ const {
150
+ nodes,
151
+ loading: nodesLoading,
152
+ wasLoaded: nodesWasLoaded,
153
+ error: nodesError,
154
+ } = useTypedSelector((state) => state.clusterNodes);
155
+ const singleClusterMode = useTypedSelector((state) => state.singleClusterMode);
156
+
157
+ useEffect(() => {
158
+ dispatch(
159
+ setHeader([
160
+ {
161
+ text: CLUSTER_PAGES.cluster.title,
162
+ link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.cluster.id}),
163
+ },
164
+ ]),
165
+ );
166
+ }, [dispatch]);
167
+
168
+ const fetchData = useCallback(() => {
169
+ dispatch(getClusterInfo(clusterName ? String(clusterName) : undefined));
170
+ dispatch(getClusterNodes());
171
+ }, [dispatch, clusterName]);
172
+
173
+ useAutofetcher(fetchData, [fetchData], true);
174
+
175
+ const versionToColor = useMemo(() => {
176
+ if (additionalVersionsProps?.getVersionToColorMap) {
177
+ return additionalVersionsProps.getVersionToColorMap();
178
+ }
179
+ return parseVersionsToVersionToColorMap(cluster.Versions);
180
+ }, [additionalVersionsProps, cluster]);
181
+
182
+ const versionsValues = useMemo(() => {
183
+ return parseNodesToVersionsValues(nodes, versionToColor);
184
+ }, [nodes, versionToColor]);
185
+
186
+ if ((loading && !wasLoaded) || (nodesLoading && !nodesWasLoaded)) {
187
+ return <Loader size="l" />;
188
+ }
189
+
190
+ if (error || nodesError) {
191
+ return <ResponseError error={error || nodesError} />;
192
+ }
193
+
194
+ let internalLink = backend + '/internal';
195
+
196
+ if (singleClusterMode && !customBackend) {
197
+ internalLink = `/internal`;
198
+ }
199
+
200
+ const {info = [], links = []} = additionalClusterProps;
201
+
202
+ const clusterInfo = getInfo(cluster, versionsValues, info, [
203
+ {title: 'Internal Viewer', url: internalLink},
204
+ ...links,
205
+ ]);
206
+
207
+ return (
208
+ <div className={b()}>
209
+ <div className={b('header')}>
210
+ <div className={b('title')}>
211
+ <EntityStatus
212
+ size="m"
213
+ status={cluster.Overall}
214
+ name={clusterTitle ?? cluster.Name ?? 'Unknown cluster'}
215
+ />
216
+ </div>
217
+ <InfoViewer dots={true} info={clusterInfo} />
218
+ </div>
219
+
220
+ <Versions nodes={nodes} versionToColor={versionToColor} />
221
+ </div>
222
+ );
223
+ };
@@ -1,4 +1,4 @@
1
- import {TTabletStateInfo, EType} from '../../types/api/tablet';
1
+ import {TTabletStateInfo, EType} from '../../../types/api/tablet';
2
2
 
3
3
  export const compareTablets = (tablet1: TTabletStateInfo, tablet2: TTabletStateInfo) => {
4
4
  if (tablet1.Type === EType.TxAllocator) {
@@ -0,0 +1,27 @@
1
+ .ydb-cluster-versions-bar {
2
+ display: flex;
3
+ flex-direction: column;
4
+
5
+ width: 600px;
6
+
7
+ & .yc-progress {
8
+ width: 100%;
9
+ }
10
+
11
+ &__versions {
12
+ display: flex;
13
+ flex-flow: row wrap;
14
+
15
+ margin-top: 6px;
16
+ }
17
+
18
+ &__version-title {
19
+ margin-left: 3px;
20
+
21
+ white-space: nowrap;
22
+ }
23
+
24
+ & .yc-progress__stack {
25
+ cursor: pointer;
26
+ }
27
+ }
@@ -0,0 +1,33 @@
1
+ import block from 'bem-cn-lite';
2
+
3
+ import {Progress} from '@gravity-ui/uikit';
4
+
5
+ import type {VersionValue} from '../../../types/versions';
6
+
7
+ import './VersionsBar.scss';
8
+
9
+ const b = block('ydb-cluster-versions-bar');
10
+
11
+ interface VersionsBarProps {
12
+ versionsValues?: VersionValue[];
13
+ }
14
+
15
+ export const VersionsBar = ({versionsValues = []}: VersionsBarProps) => {
16
+ return (
17
+ <div className={b()}>
18
+ <Progress value={100} stack={versionsValues} view="thin" />
19
+ <div className={b('versions')}>
20
+ {versionsValues.map((item, index) => (
21
+ <div
22
+ className={b('version-title')}
23
+ style={{color: item.color}}
24
+ key={item.version}
25
+ title={item.version}
26
+ >
27
+ {`${item.version}${index === versionsValues.length - 1 ? '' : ','}`}
28
+ </div>
29
+ ))}
30
+ </div>
31
+ </div>
32
+ );
33
+ };
@@ -2,10 +2,10 @@ import React, {useEffect} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
  import {useHistory} from 'react-router';
5
- import {Breadcrumbs, BreadcrumbsItem, Link} from '@gravity-ui/uikit';
5
+ import {Breadcrumbs, BreadcrumbsItem} from '@gravity-ui/uikit';
6
6
 
7
7
  import Divider from '../../components/Divider/Divider';
8
- import {Icon} from '../../components/Icon';
8
+ import {ExternalLinkWithIcon} from '../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
9
9
 
10
10
  import {backend, customBackend} from '../../store';
11
11
  import {getHostInfo} from '../../store/reducers/host';
@@ -72,10 +72,7 @@ function Header({clusterName}: HeaderProps) {
72
72
  </div>
73
73
 
74
74
  <div className={b('cluster-name-wrapper')}>
75
- <Link href={link} target="_blank">
76
- Internal viewer{' '}
77
- <Icon name="external" viewBox={'0 0 16 16'} width={16} height={16} />
78
- </Link>
75
+ <ExternalLinkWithIcon title={'Internal Viewer'} url={link} />
79
76
  {clusterNameFinal && (
80
77
  <React.Fragment>
81
78
  <div className={b('divider')}>
@@ -31,7 +31,6 @@ import {
31
31
  getComputeNodes,
32
32
  } from '../../store/reducers/nodes';
33
33
  import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
34
- import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
35
34
 
36
35
  import {isDatabaseEntityType} from '../Tenant/utils/schema';
37
36
 
@@ -129,18 +128,8 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
129
128
  );
130
129
  };
131
130
 
132
- const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
133
- dispatch(showTooltip(...args));
134
- };
135
-
136
- const onHideTooltip = () => {
137
- dispatch(hideTooltip());
138
- };
139
-
140
131
  const renderTable = () => {
141
132
  const columns = getNodesColumns({
142
- showTooltip: onShowTooltip,
143
- hideTooltip: onHideTooltip,
144
133
  getNodeRef: additionalNodesInfo.getNodeRef,
145
134
  });
146
135
 
@@ -1,7 +1,7 @@
1
1
  import DataTable, {Column} from '@gravity-ui/react-data-table';
2
2
  import {Popover} from '@gravity-ui/uikit';
3
3
 
4
- import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
4
+ import {PoolsGraph} from '../../components/PoolsGraph/PoolsGraph';
5
5
  import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
6
6
  import {TabletsStatistic} from '../../components/TabletsStatistic';
7
7
  import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
@@ -10,21 +10,13 @@ import type {NodeAddress} from '../../utils/nodes';
10
10
  import {formatBytesToGigabyte} from '../../utils/index';
11
11
 
12
12
  import type {INodesPreparedEntity} from '../../types/store/nodes';
13
- import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
14
13
 
15
14
  interface GetNodesColumnsProps {
16
- showTooltip: (...args: Parameters<typeof externalShowTooltip>) => void;
17
- hideTooltip: VoidFunction;
18
15
  tabletsPath?: string;
19
16
  getNodeRef?: (node?: NodeAddress) => string;
20
17
  }
21
18
 
22
- export function getNodesColumns({
23
- showTooltip,
24
- hideTooltip,
25
- tabletsPath,
26
- getNodeRef,
27
- }: GetNodesColumnsProps) {
19
+ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps) {
28
20
  const columns: Column<INodesPreparedEntity>[] = [
29
21
  {
30
22
  name: 'NodeId',
@@ -96,16 +88,7 @@ export function getNodesColumns({
96
88
  }
97
89
  }, 0),
98
90
  defaultOrder: DataTable.DESCENDING,
99
- render: ({row}) =>
100
- row.PoolStats ? (
101
- <PoolsGraph
102
- onMouseEnter={showTooltip}
103
- onMouseLeave={hideTooltip}
104
- pools={row.PoolStats}
105
- />
106
- ) : (
107
- '—'
108
- ),
91
+ render: ({row}) => (row.PoolStats ? <PoolsGraph pools={row.PoolStats} /> : '—'),
109
92
  align: DataTable.LEFT,
110
93
  width: '120px',
111
94
  },
@@ -52,6 +52,10 @@
52
52
  text-transform: uppercase;
53
53
  }
54
54
 
55
+ &__loader {
56
+ width: 25px;
57
+ }
58
+
55
59
  .info-viewer__items {
56
60
  grid-template-columns: auto;
57
61
  }
@@ -108,9 +108,10 @@ export const Tablet = () => {
108
108
  <Icon name="external" />
109
109
  </a>
110
110
  {Leader && <Tag text="Leader" type="blue" />}
111
+ <span className={b('loader')}>{loading && <Loader size="s" />}</span>
111
112
  </div>
112
113
  <TabletInfo tablet={tablet} tenantPath={tenantPath} />
113
- <TabletControls tablet={tablet} />
114
+ <TabletControls tablet={tablet} fetchData={fetchData} />
114
115
  </div>
115
116
  <div className={b('rigth-pane')}>
116
117
  <TabletTable history={history} />
@@ -17,18 +17,19 @@ type VisibleDialogType = EVisibleDialogType | null;
17
17
 
18
18
  interface TabletControlsProps {
19
19
  tablet: TTabletStateInfo;
20
+ fetchData: VoidFunction;
20
21
  }
21
22
 
22
- export const TabletControls = ({tablet}: TabletControlsProps) => {
23
+ export const TabletControls = ({tablet, fetchData}: TabletControlsProps) => {
23
24
  const {TabletId, HiveId} = tablet;
24
25
 
25
26
  const [isDialogVisible, setIsDialogVisible] = useState(false);
26
27
  const [visibleDialogType, setVisibleDialogType] = useState<VisibleDialogType>(null);
27
- const [isTabletActionsDisabled, setIsTabletActionsDisabled] = useState(false);
28
+ const [isTabletActionLoading, setIsTabletActionLoading] = useState(false);
28
29
 
29
30
  // Enable controls after data update
30
31
  useEffect(() => {
31
- setIsTabletActionsDisabled(false);
32
+ setIsTabletActionLoading(false);
32
33
  }, [tablet]);
33
34
 
34
35
  const makeShowDialog = (type: VisibleDialogType) => () => {
@@ -46,15 +47,15 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
46
47
  };
47
48
 
48
49
  const _onKillClick = () => {
49
- setIsTabletActionsDisabled(true);
50
+ setIsTabletActionLoading(true);
50
51
  return window.api.killTablet(TabletId);
51
52
  };
52
53
  const _onStopClick = () => {
53
- setIsTabletActionsDisabled(true);
54
+ setIsTabletActionLoading(true);
54
55
  return window.api.stopTablet(TabletId, HiveId);
55
56
  };
56
57
  const _onResumeClick = () => {
57
- setIsTabletActionsDisabled(true);
58
+ setIsTabletActionLoading(true);
58
59
  return window.api.resumeTablet(TabletId, HiveId);
59
60
  };
60
61
 
@@ -62,25 +63,11 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
62
63
  return HiveId && HiveId !== '0';
63
64
  };
64
65
 
65
- const isDisabledResume = () => {
66
- if (isTabletActionsDisabled) {
67
- return true;
68
- }
69
-
70
- return tablet.State !== ETabletState.Stopped && tablet.State !== ETabletState.Dead;
71
- };
72
-
73
- const isDisabledKill = () => {
74
- return isTabletActionsDisabled;
75
- };
76
-
77
- const isDisabledStop = () => {
78
- if (isTabletActionsDisabled) {
79
- return true;
80
- }
66
+ const isDisabledResume =
67
+ tablet.State !== ETabletState.Stopped && tablet.State !== ETabletState.Dead;
81
68
 
82
- return tablet.State === ETabletState.Stopped || tablet.State === ETabletState.Deleted;
83
- };
69
+ const isDisabledStop =
70
+ tablet.State === ETabletState.Stopped || tablet.State === ETabletState.Deleted;
84
71
 
85
72
  const renderDialog = () => {
86
73
  if (!isDialogVisible) {
@@ -95,6 +82,7 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
95
82
  text={i18n('dialog.kill')}
96
83
  onClose={hideDialog}
97
84
  onConfirm={_onKillClick}
85
+ onConfirmActionFinish={fetchData}
98
86
  />
99
87
  );
100
88
  }
@@ -105,6 +93,7 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
105
93
  text={i18n('dialog.stop')}
106
94
  onClose={hideDialog}
107
95
  onConfirm={_onStopClick}
96
+ onConfirmActionFinish={fetchData}
108
97
  />
109
98
  );
110
99
  }
@@ -115,6 +104,7 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
115
104
  text={i18n('dialog.resume')}
116
105
  onClose={hideDialog}
117
106
  onConfirm={_onResumeClick}
107
+ onConfirmActionFinish={fetchData}
118
108
  />
119
109
  );
120
110
  }
@@ -128,7 +118,7 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
128
118
  <Button
129
119
  onClick={showKillDialog}
130
120
  view="action"
131
- disabled={isDisabledKill()}
121
+ loading={isTabletActionLoading}
132
122
  className={b('control')}
133
123
  >
134
124
  {i18n('controls.kill')}
@@ -138,7 +128,8 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
138
128
  <Button
139
129
  onClick={showStopDialog}
140
130
  view="action"
141
- disabled={isDisabledStop()}
131
+ disabled={isDisabledStop}
132
+ loading={!isDisabledStop && isTabletActionLoading}
142
133
  className={b('control')}
143
134
  >
144
135
  {i18n('controls.stop')}
@@ -146,7 +137,8 @@ export const TabletControls = ({tablet}: TabletControlsProps) => {
146
137
  <Button
147
138
  onClick={showResumeDialog}
148
139
  view="action"
149
- disabled={isDisabledResume()}
140
+ disabled={isDisabledResume}
141
+ loading={!isDisabledResume && isTabletActionLoading}
150
142
  className={b('control')}
151
143
  >
152
144
  {i18n('controls.resume')}
@@ -12,7 +12,6 @@ import {Loader} from '../../components/Loader';
12
12
  import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
13
13
  import {ETabletState, EType, TTabletStateInfo} from '../../types/api/tablet';
14
14
 
15
- import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
15
  import {
17
16
  getTabletsInfo,
18
17
  clearWasLoadingFlag,
@@ -89,23 +88,8 @@ export const Tablets = ({path, nodeId, className}: TabletsProps) => {
89
88
  dispatch(setTypeFilter(value as EType[]));
90
89
  };
91
90
 
92
- const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
93
- dispatch(showTooltip(...args));
94
- };
95
-
96
- const onHideTooltip = () => {
97
- dispatch(hideTooltip());
98
- };
99
-
100
91
  const renderTablet = (tabletIndex: number) => {
101
- return (
102
- <Tablet
103
- onMouseLeave={onHideTooltip}
104
- onMouseEnter={onShowTooltip}
105
- tablet={tabletsToRender[tabletIndex]}
106
- key={tabletIndex}
107
- />
108
- );
92
+ return <Tablet tablet={tabletsToRender[tabletIndex]} key={tabletIndex} />;
109
93
  };
110
94
 
111
95
  const renderContent = () => {
@@ -12,7 +12,6 @@ import {Tablet} from '../../components/Tablet';
12
12
  import {AccessDenied} from '../../components/Errors/403';
13
13
 
14
14
  import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
15
- import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
15
  import {
17
16
  getTabletsInfo,
18
17
  clearWasLoadingFlag,
@@ -30,8 +29,6 @@ class TabletsFilters extends React.Component {
30
29
  static propTypes = {
31
30
  wasLoaded: PropTypes.bool,
32
31
  loading: PropTypes.bool,
33
- showTooltip: PropTypes.func,
34
- hideTooltip: PropTypes.func,
35
32
  getTabletsInfo: PropTypes.func,
36
33
  timeoutForRequest: PropTypes.number,
37
34
  path: PropTypes.string,
@@ -141,17 +138,10 @@ class TabletsFilters extends React.Component {
141
138
  };
142
139
 
143
140
  renderTablet = (index, key) => {
144
- const {filteredTablets, hideTooltip, showTooltip, size} = this.props;
141
+ const {filteredTablets, size} = this.props;
145
142
 
146
143
  return (
147
- <Tablet
148
- onMouseLeave={hideTooltip}
149
- onMouseEnter={showTooltip}
150
- tablet={filteredTablets[index]}
151
- key={key}
152
- size={size}
153
- className={b('tablet')}
154
- />
144
+ <Tablet tablet={filteredTablets[index]} key={key} size={size} className={b('tablet')} />
155
145
  );
156
146
  };
157
147
 
@@ -333,8 +323,6 @@ const mapStateToProps = (state) => {
333
323
 
334
324
  const mapDispatchToProps = {
335
325
  getTabletsInfo,
336
- hideTooltip,
337
- showTooltip,
338
326
  clearWasLoadingFlag,
339
327
  setStateFilter,
340
328
  setTypeFilter,
@@ -3,13 +3,13 @@ import block from 'bem-cn-lite';
3
3
  import qs from 'qs';
4
4
 
5
5
  import type {IPreparedConsumerData} from '../../../../../types/store/topic';
6
+ import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
6
7
  import {SpeedMultiMeter} from '../../../../../components/SpeedMultiMeter';
7
8
  import {InternalLink} from '../../../../../components/InternalLink';
8
9
  import {formatMsToUptime} from '../../../../../utils';
9
10
  import routes, {createHref} from '../../../../../routes';
10
11
 
11
12
  import {TenantTabsGroups} from '../../../TenantPages';
12
- import {GeneralPagesIds} from '../../DiagnosticsPages';
13
13
 
14
14
  import {
15
15
  CONSUMERS_COLUMNS_IDS,
@@ -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]: GeneralPagesIds.partitions,
45
+ [TenantTabsGroups.generalTab]: TENANT_DIAGNOSTICS_TABS_IDS.partitions,
46
46
  selectedConsumer: row.name,
47
47
  })}
48
48
  >