Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f1aacd3

Browse files
committedFeb 7, 2025·
feat(Node): rework page
1 parent cc81623 commit f1aacd3

23 files changed

+330
-381
lines changed
 

‎src/components/BasicNodeViewer/BasicNodeViewer.scss

-35
This file was deleted.

‎src/components/BasicNodeViewer/BasicNodeViewer.tsx

-73
This file was deleted.

‎src/components/BasicNodeViewer/index.ts

-1
This file was deleted.

‎src/components/EntityPageTitle/EntityPageTitle.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {EFlag} from '../../types/api/enums';
1+
import {EFlag} from '../../types/api/enums';
22
import {cn} from '../../utils/cn';
33
import {StatusIcon} from '../StatusIcon/StatusIcon';
44

@@ -8,12 +8,17 @@ const b = cn('ydb-entity-page-title');
88

99
interface EntityPageTitleProps {
1010
entityName: React.ReactNode;
11-
status: EFlag;
11+
status?: EFlag;
1212
id: React.ReactNode;
1313
className?: string;
1414
}
1515

16-
export function EntityPageTitle({entityName, status, id, className}: EntityPageTitleProps) {
16+
export function EntityPageTitle({
17+
entityName,
18+
status = EFlag.Grey,
19+
id,
20+
className,
21+
}: EntityPageTitleProps) {
1722
return (
1823
<div className={b(null, className)}>
1924
<span className={b('prefix')}>{entityName}</span>

‎src/components/FullNodeViewer/FullNodeViewer.scss

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,11 @@
33
.full-node-viewer {
44
@include mixins.body-2-typography();
55

6-
&__common-info {
6+
&__section {
77
display: flex;
88
flex-direction: column;
9-
justify-content: flex-start;
10-
align-items: stretch;
11-
}
129

13-
&__section {
14-
border-radius: 10px;
10+
width: 500px;
1511

1612
&_pools {
1713
display: grid;
@@ -26,8 +22,6 @@
2622
}
2723

2824
&__section-title {
29-
margin: 15px 0 10px;
30-
31-
font-weight: 600;
25+
@include mixins.info-viewer-title();
3226
}
3327
}
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,110 @@
1+
import {Flex} from '@gravity-ui/uikit';
2+
13
import type {PreparedNode} from '../../store/reducers/node/types';
24
import {cn} from '../../utils/cn';
3-
import {LOAD_AVERAGE_TIME_INTERVALS} from '../../utils/constants';
5+
import {useNodeDeveloperUIHref} from '../../utils/hooks/useNodeDeveloperUIHref';
46
import {InfoViewer} from '../InfoViewer/InfoViewer';
57
import type {InfoViewerItem} from '../InfoViewer/InfoViewer';
8+
import {LinkWithIcon} from '../LinkWithIcon/LinkWithIcon';
69
import {PoolUsage} from '../PoolUsage/PoolUsage';
710
import {ProgressViewer} from '../ProgressViewer/ProgressViewer';
811
import {NodeUptime} from '../UptimeViewer/UptimeViewer';
912

13+
import i18n from './i18n';
14+
1015
import './FullNodeViewer.scss';
1116

1217
const b = cn('full-node-viewer');
1318

1419
interface FullNodeViewerProps {
15-
node: PreparedNode | undefined;
20+
node?: PreparedNode;
1621
className?: string;
1722
}
23+
const getLoadAverageIntervalTitle = (index: number) => {
24+
return [i18n('la-interval-1m'), i18n('la-interval-5m'), i18n('la-interval-15m')][index];
25+
};
1826

1927
export const FullNodeViewer = ({node, className}: FullNodeViewerProps) => {
20-
const endpointsInfo = node?.Endpoints?.map(({Name, Address}) => ({
21-
label: Name,
22-
value: Address,
23-
}));
28+
const developerUIHref = useNodeDeveloperUIHref(node);
2429

2530
const commonInfo: InfoViewerItem[] = [];
2631

27-
// Do not add DB field for static nodes (they have no Tenants)
2832
if (node?.Tenants?.length) {
29-
commonInfo.push({label: 'Database', value: node.Tenants[0]});
33+
commonInfo.push({label: i18n('database'), value: node.Tenants[0]});
3034
}
3135

3236
commonInfo.push(
33-
{label: 'Version', value: node?.Version},
37+
{label: i18n('version'), value: node?.Version},
3438
{
35-
label: 'Uptime',
39+
label: i18n('uptime'),
3640
value: <NodeUptime StartTime={node?.StartTime} DisconnectTime={node?.DisconnectTime} />,
3741
},
38-
{label: 'DC', value: node?.DataCenterDescription || node?.DC},
39-
{label: 'Rack', value: node?.Rack},
42+
{label: i18n('dc'), value: node?.DataCenterDescription || node?.DC},
4043
);
4144

45+
if (node?.Rack) {
46+
commonInfo.push({label: i18n('rack'), value: node?.Rack});
47+
}
48+
49+
if (developerUIHref) {
50+
commonInfo.push({
51+
label: i18n('links'),
52+
value: <LinkWithIcon url={developerUIHref} title={i18n('developer-ui')} />,
53+
});
54+
}
55+
56+
const endpointsInfo = node?.Endpoints?.map(({Name, Address}) => ({
57+
label: Name,
58+
value: Address,
59+
}));
60+
4261
const averageInfo = node?.LoadAveragePercents?.map((load, loadIndex) => ({
43-
label: LOAD_AVERAGE_TIME_INTERVALS[loadIndex],
62+
label: getLoadAverageIntervalTitle(loadIndex),
4463
value: (
4564
<ProgressViewer value={load} percents={true} colorizeProgress={true} capacity={100} />
4665
),
4766
}));
4867

68+
if (!node) {
69+
return <div className="error">{i18n('no-data')}</div>;
70+
}
71+
4972
return (
50-
<div className={`${b()} ${className}`}>
51-
{node ? (
52-
<div className={b('common-info')}>
73+
<div className={b(null, className)}>
74+
<Flex wrap gap={2}>
75+
<Flex direction="column" gap={2}>
76+
<InfoViewer
77+
title={i18n('title.common-info')}
78+
className={b('section')}
79+
info={commonInfo}
80+
/>
81+
82+
{endpointsInfo && endpointsInfo.length ? (
83+
<InfoViewer
84+
title={i18n('title.endpoints')}
85+
className={b('section')}
86+
info={endpointsInfo}
87+
/>
88+
) : null}
89+
</Flex>
90+
91+
<Flex direction="column" gap={2}>
5392
<div>
54-
<div className={b('section-title')}>Pools</div>
93+
<div className={b('section-title')}>{i18n('title.pools')}</div>
5594
<div className={b('section', {pools: true})}>
5695
{node?.PoolStats?.map((pool, poolIndex) => (
5796
<PoolUsage key={poolIndex} data={pool} />
5897
))}
5998
</div>
6099
</div>
61100

62-
{endpointsInfo && endpointsInfo.length && (
63-
<InfoViewer
64-
title="Endpoints"
65-
className={b('section')}
66-
info={endpointsInfo}
67-
/>
68-
)}
69-
70-
<InfoViewer title="Common info" className={b('section')} info={commonInfo} />
71-
72101
<InfoViewer
73-
title="Load average"
102+
title={i18n('title.load-average')}
74103
className={b('section', {average: true})}
75104
info={averageInfo}
76105
/>
77-
</div>
78-
) : (
79-
<div className="error">no data</div>
80-
)}
106+
</Flex>
107+
</Flex>
81108
</div>
82109
);
83110
};
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"database": "Database",
3+
"uptime": "Uptime",
4+
"version": "Version",
5+
"dc": "DC",
6+
"rack": "Rack",
7+
"links": "Links",
8+
9+
"la-interval-1m": "1 min",
10+
"la-interval-5m": "5 min",
11+
"la-interval-15m": "15 min",
12+
13+
"developer-ui": "Developer UI",
14+
"no-data": "No data",
15+
16+
"title.common-info": "Common info",
17+
"title.endpoints": "Endpoints",
18+
"title.pools": "Pools",
19+
"title.load-average": "Load average"
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {registerKeysets} from '../../../utils/i18n';
2+
3+
import en from './en.json';
4+
5+
const COMPONENT = 'ydb-node-info';
6+
7+
export default registerKeysets(COMPONENT, {en});

‎src/components/PageMeta/PageMeta.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import React from 'react';
2+
13
import {Flex} from '@gravity-ui/uikit';
24

35
import {cn} from '../../utils/cn';
@@ -14,13 +16,15 @@ interface PageMetaProps {
1416
loading?: boolean;
1517
}
1618

19+
const separator = '\u00a0\u00a0\u00B7\u00a0\u00a0';
20+
1721
export function PageMeta({items, loading}: PageMetaProps) {
1822
const renderContent = () => {
1923
if (loading) {
2024
return <Skeleton className={b('skeleton')} />;
2125
}
2226

23-
return items.filter((item) => Boolean(item)).join('\u00a0\u00a0\u00B7\u00a0\u00a0');
27+
return items.filter((item) => Boolean(item)).join(separator);
2428
};
2529

2630
return <div className={b('info')}>{renderContent()}</div>;

‎src/components/TabletsStatistic/TabletsStatistic.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Link} from 'react-router-dom';
22

3-
import {TABLETS, getDefaultNodePath} from '../../containers/Node/NodePages';
3+
import {getDefaultNodePath} from '../../containers/Node/NodePages';
44
import type {TTabletStateInfo} from '../../types/api/tablet';
55
import {cn} from '../../utils/cn';
66
import {getTabletLabel} from '../../utils/constants';
@@ -31,7 +31,7 @@ interface TabletsStatisticProps {
3131

3232
export const TabletsStatistic = ({tablets = [], database, nodeId}: TabletsStatisticProps) => {
3333
const renderTabletInfo = (item: ReturnType<typeof prepareTablets>[number], index: number) => {
34-
const tabletsPath = getDefaultNodePath(nodeId, {database}, TABLETS);
34+
const tabletsPath = getDefaultNodePath(nodeId, {database}, 'tablets');
3535

3636
const label = `${item.label}: ${item.count}`;
3737
const className = b('tablet', {state: item.state?.toLowerCase()});

0 commit comments

Comments
 (0)
Please sign in to comment.