Skip to content

Commit 5d51dc8

Browse files
refactor(Tablet): add and use ContentWithPopup (#401)
1 parent 831c17f commit 5d51dc8

File tree

13 files changed

+117
-149
lines changed

13 files changed

+117
-149
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {ReactNode, useRef, useState} from 'react';
2+
3+
import {Popup, PopupProps} from '@gravity-ui/uikit';
4+
5+
interface ContentWithPopupProps extends PopupProps {
6+
content: ReactNode;
7+
className?: string;
8+
children?: ReactNode;
9+
}
10+
11+
export const ContentWithPopup = ({
12+
children,
13+
content,
14+
className,
15+
hasArrow = true,
16+
placement = ['top', 'bottom'],
17+
...props
18+
}: ContentWithPopupProps) => {
19+
const [isPopupVisible, setIsPopupVisible] = useState(false);
20+
const anchor = useRef(null);
21+
22+
const showPopup = () => {
23+
setIsPopupVisible(true);
24+
};
25+
26+
const hidePopup = () => {
27+
setIsPopupVisible(false);
28+
};
29+
30+
return (
31+
<>
32+
<Popup
33+
anchorRef={anchor}
34+
open={isPopupVisible}
35+
placement={placement}
36+
hasArrow={hasArrow}
37+
{...props}
38+
>
39+
{content}
40+
</Popup>
41+
<span
42+
className={className}
43+
ref={anchor}
44+
onMouseEnter={showPopup}
45+
onMouseLeave={hidePopup}
46+
>
47+
{children}
48+
</span>
49+
</>
50+
);
51+
};

src/components/NodeHostWrapper/NodeHostWrapper.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {getDefaultNodePath} from '../../containers/Node/NodePages';
77
import {isUnavailableNode, NodeAddress} from '../../utils/nodes';
88

99
import EntityStatus from '../EntityStatus/EntityStatus';
10-
import {NodeEndpointsTooltip} from '../Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
10+
import {NodeEndpointsTooltipContent} from '../TooltipsContent';
1111
import {IconWrapper} from '../Icon';
1212

1313
import './NodeHostWrapper.scss';
@@ -31,7 +31,7 @@ export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
3131
<div className={b()}>
3232
<Popover
3333
disabled={!isNodeAvailable}
34-
content={<NodeEndpointsTooltip data={node} />}
34+
content={<NodeEndpointsTooltipContent data={node} />}
3535
placement={['top', 'bottom']}
3636
behavior={PopoverBehavior.Immediate}
3737
>

src/components/Tablet/Tablet.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
}
2323
}
2424

25+
&__popup-content {
26+
padding: 10px;
27+
}
28+
2529
&__type {
2630
line-height: 17px;
2731

src/components/Tablet/Tablet.tsx

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,35 @@
1-
import {useRef} from 'react';
21
import cn from 'bem-cn-lite';
32

43
import type {TTabletStateInfo} from '../../types/api/tablet';
5-
import type {ShowTooltipFunction} from '../../types/store/tooltip';
64
import {getTabletLabel} from '../../utils/constants';
75
import routes, {createHref} from '../../routes';
86

7+
import {ContentWithPopup} from '../ContentWithPopup/ContentWithPopup';
98
import {InternalLink} from '../InternalLink';
9+
import {TabletTooltipContent} from '../TooltipsContent';
1010

1111
import './Tablet.scss';
1212

1313
const b = cn('tablet');
1414

1515
interface TabletProps {
1616
tablet?: TTabletStateInfo;
17-
onMouseEnter?: (...args: Parameters<ShowTooltipFunction>) => void;
18-
onMouseLeave?: VoidFunction;
1917
}
2018

21-
export const Tablet = ({
22-
tablet = {},
23-
onMouseEnter = () => {},
24-
onMouseLeave = () => {},
25-
}: TabletProps) => {
26-
const ref = useRef(null);
27-
28-
const _onTabletMouseEnter = () => {
29-
onMouseEnter(ref.current, tablet, 'tablet');
30-
};
31-
32-
const _onTabletClick = () => {
33-
const {TabletId: id} = tablet;
34-
35-
if (id) {
36-
onMouseLeave();
37-
}
38-
};
39-
19+
export const Tablet = ({tablet = {}}: TabletProps) => {
4020
const {TabletId: id} = tablet;
4121
const status = tablet.Overall?.toLowerCase();
4222

4323
return (
44-
<InternalLink
45-
onClick={_onTabletClick}
46-
to={id && createHref(routes.tablet, {id})}
24+
<ContentWithPopup
4725
className={b('wrapper')}
26+
content={<TabletTooltipContent data={tablet} className={b('popup-content')} />}
4827
>
49-
<div
50-
ref={ref}
51-
className={b({status})}
52-
onMouseEnter={_onTabletMouseEnter}
53-
onMouseLeave={onMouseLeave}
54-
>
55-
<div className={b('type')}>{[getTabletLabel(tablet.Type)]}</div>
56-
</div>
57-
</InternalLink>
28+
<InternalLink to={id && createHref(routes.tablet, {id})}>
29+
<div className={b({status})}>
30+
<div className={b('type')}>{[getTabletLabel(tablet.Type)]}</div>
31+
</div>
32+
</InternalLink>
33+
</ContentWithPopup>
5834
);
5935
};

src/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.scss renamed to src/components/TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.ydb-node-endpoints-tooltip {
1+
.ydb-node-endpoints-tooltip-content {
22
.info-viewer__value {
33
min-width: 70px;
44
}

src/components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip.tsx renamed to src/components/TooltipsContent/NodeEndpointsTooltipContent/NodeEndpointsTooltipContent.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import type {TSystemStateInfo} from '../../../types/api/nodes';
44

55
import {InfoViewer, InfoViewerItem} from '../../InfoViewer';
66

7-
import './NodeEndpointsTooltip.scss';
7+
import './NodeEndpointsTooltipContent.scss';
88

9-
const b = block('ydb-node-endpoints-tooltip');
9+
const b = block('ydb-node-endpoints-tooltip-content');
1010

1111
interface NodeEdpointsTooltipProps {
1212
data?: TSystemStateInfo;
1313
}
1414

15-
export const NodeEndpointsTooltip = ({data}: NodeEdpointsTooltipProps) => {
15+
export const NodeEndpointsTooltipContent = ({data}: NodeEdpointsTooltipProps) => {
1616
const info: InfoViewerItem[] = [];
1717

1818
if (data?.Rack) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type {TTabletStateInfo} from '../../../types/api/tablet';
2+
3+
import {calcUptime} from '../../../utils';
4+
import {InfoViewer, createInfoFormatter, formatObject} from '../../InfoViewer';
5+
6+
const formatTablet = createInfoFormatter<TTabletStateInfo>({
7+
values: {
8+
ChangeTime: (value) => calcUptime(value),
9+
},
10+
labels: {
11+
TabletId: 'Tablet',
12+
},
13+
defaultValueFormatter: (value) => value && String(value),
14+
});
15+
16+
interface TabletTooltipContentProps {
17+
data?: TTabletStateInfo;
18+
className?: string;
19+
}
20+
21+
export const TabletTooltipContent = ({data = {}, className}: TabletTooltipContentProps) => {
22+
const {TabletId, NodeId, State, Type, ChangeTime, Generation} = data;
23+
24+
const info = formatObject(formatTablet, {
25+
TabletId,
26+
NodeId,
27+
State,
28+
Type,
29+
ChangeTime,
30+
Generation,
31+
});
32+
33+
return <InfoViewer className={className} info={info} dots={false} size={'s'} />;
34+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './NodeEndpointsTooltipContent/NodeEndpointsTooltipContent';
2+
export * from './TabletTooltipContent/TabletTooltipContent';

src/containers/ClusterInfo/ClusterInfo.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {Loader} from '../../components/Loader';
1616
import {ResponseError} from '../../components/Errors/ResponseError';
1717

1818
import type {AdditionalVersionsProps} from '../../types/additionalProps';
19-
import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
2019
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
2120
import {getClusterNodes} from '../../store/reducers/clusterNodes/clusterNodes';
2221
import {backend, customBackend} from '../../store';
@@ -91,14 +90,6 @@ export const ClusterInfo = ({
9190
return parseNodesToVersionsValues(nodes, versionToColor);
9291
}, [nodes, versionToColor]);
9392

94-
const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
95-
dispatch(showTooltip(...args));
96-
};
97-
98-
const onHideTooltip = () => {
99-
dispatch(hideTooltip());
100-
};
101-
10293
const getInfo = () => {
10394
let link = backend + '/internal';
10495

@@ -183,12 +174,7 @@ export const ClusterInfo = ({
183174
{cluster?.SystemTablets &&
184175
cluster.SystemTablets.sort(compareTablets).map(
185176
(tablet, tabletIndex) => (
186-
<Tablet
187-
onMouseEnter={onShowTooltip}
188-
onMouseLeave={onHideTooltip}
189-
key={tabletIndex}
190-
tablet={tablet}
191-
/>
177+
<Tablet key={tabletIndex} tablet={tablet} />
192178
),
193179
)}
194180
</div>

src/containers/Tablets/Tablets.tsx

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {Loader} from '../../components/Loader';
1212
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
1313
import {ETabletState, EType, TTabletStateInfo} from '../../types/api/tablet';
1414

15-
import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
1615
import {
1716
getTabletsInfo,
1817
clearWasLoadingFlag,
@@ -89,23 +88,8 @@ export const Tablets = ({path, nodeId, className}: TabletsProps) => {
8988
dispatch(setTypeFilter(value as EType[]));
9089
};
9190

92-
const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
93-
dispatch(showTooltip(...args));
94-
};
95-
96-
const onHideTooltip = () => {
97-
dispatch(hideTooltip());
98-
};
99-
10091
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} />;
10993
};
11094

11195
const renderContent = () => {

0 commit comments

Comments
 (0)