Skip to content

Commit f641763

Browse files
fix: review
1 parent e7eec6b commit f641763

File tree

1 file changed

+108
-61
lines changed

1 file changed

+108
-61
lines changed

src/containers/Node/Node.tsx

Lines changed: 108 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
22

3+
import type {TabsItemProps} from '@gravity-ui/uikit';
34
import {Tabs} from '@gravity-ui/uikit';
5+
import {skipToken} from '@reduxjs/toolkit/query';
46
import {Helmet} from 'react-helmet-async';
57
import {useRouteMatch} from 'react-router-dom';
68
import {useQueryParams} from 'use-query-params';
@@ -18,6 +20,7 @@ import {
1820
} from '../../store/reducers/capabilities/hooks';
1921
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
2022
import {nodeApi} from '../../store/reducers/node/node';
23+
import type {PreparedNode} from '../../store/reducers/node/types';
2124
import {cn} from '../../utils/cn';
2225
import {useAutoRefreshInterval, useTypedDispatch} from '../../utils/hooks';
2326
import {PaginatedStorage} from '../Storage/PaginatedStorage';
@@ -41,20 +44,21 @@ export function Node() {
4144

4245
const match = useRouteMatch<{id: string; activeTab: string}>(routes.node);
4346

44-
// NodeId is always defined here because the page is wrapped with specific route Router
45-
const nodeId = match?.params.id as string;
47+
const nodeId = match?.params.id;
4648
const activeTabIdFromQuery = match?.params.activeTab;
4749

4850
const [{database: tenantNameFromQuery}] = useQueryParams(nodePageQueryParams);
4951

5052
const activeTabId = nodePageTabSchema.parse(activeTabIdFromQuery);
5153

5254
const [autoRefreshInterval] = useAutoRefreshInterval();
55+
56+
const params = nodeId ? {nodeId} : skipToken;
5357
const {
5458
currentData: node,
5559
isLoading,
5660
error,
57-
} = nodeApi.useGetNodeInfoQuery({nodeId}, {pollingInterval: autoRefreshInterval});
61+
} = nodeApi.useGetNodeInfoQuery(params, {pollingInterval: autoRefreshInterval});
5862

5963
const capabilitiesLoaded = useCapabilitiesLoaded();
6064
const isDiskPagesAvailable = useDiskPagesAvailable();
@@ -92,57 +96,113 @@ export function Node() {
9296
}
9397
}, [dispatch, tenantName, nodeId, isLoading, isStorageNode]);
9498

95-
const renderHelmet = () => {
96-
const host = node?.Host ? node.Host : i18n('node');
97-
return (
98-
<Helmet
99-
titleTemplate={`%s — ${host} — YDB Monitoring`}
100-
defaultTitle={`${host} — YDB Monitoring`}
101-
>
102-
<title>{activeTab.title}</title>
103-
</Helmet>
104-
);
105-
};
99+
return (
100+
<div className={b(null)} ref={container}>
101+
{<NodePageHelmet node={node} activeTabTitle={activeTab.title} />}
102+
{<NodePageMeta node={node} loading={pageLoading} />}
103+
{<NodePageTitle node={node} />}
104+
{error ? <ResponseError error={error} className={b('error')} /> : null}
105+
{<NodePageInfo node={node} loading={pageLoading} />}
106+
{nodeId ? (
107+
<NodePageContent
108+
nodeId={nodeId}
109+
tenantName={tenantName}
110+
activeTabId={activeTab.id}
111+
tabs={nodeTabs}
112+
parentContainer={container}
113+
/>
114+
) : null}
115+
</div>
116+
);
117+
}
106118

107-
const renderPageMeta = () => {
108-
const hostItem = node?.Host ? `${i18n('fqdn')}: ${node.Host}` : undefined;
109-
const dcItem = node?.DC ? `${i18n('dc')}: ${node.DC}` : undefined;
119+
interface NodePageHelmetProps {
120+
node?: PreparedNode;
121+
activeTabTitle?: string;
122+
}
110123

111-
return (
112-
<PageMetaWithAutorefresh
113-
loading={pageLoading}
114-
items={[hostItem, dcItem]}
115-
className={b('meta')}
116-
/>
117-
);
118-
};
124+
function NodePageHelmet({node, activeTabTitle}: NodePageHelmetProps) {
125+
const host = node?.Host ? node.Host : i18n('node');
126+
return (
127+
<Helmet
128+
titleTemplate={`%s — ${host} — YDB Monitoring`}
129+
defaultTitle={`${host} — YDB Monitoring`}
130+
>
131+
<title>{activeTabTitle}</title>
132+
</Helmet>
133+
);
134+
}
119135

120-
const renderPageTitle = () => {
121-
return (
122-
<EntityPageTitle
123-
entityName={i18n('node')}
124-
status={node?.SystemState}
125-
id={node?.NodeId}
126-
className={b('title')}
127-
/>
128-
);
129-
};
136+
interface NodePageMetaProps {
137+
node?: PreparedNode;
138+
loading?: boolean;
139+
}
130140

131-
const renderInfo = () => {
132-
if (pageLoading) {
133-
return <InfoViewerSkeleton className={b('info')} rows={10} />;
134-
}
141+
function NodePageMeta({node, loading}: NodePageMetaProps) {
142+
const hostItem = node?.Host ? `${i18n('fqdn')}: ${node.Host}` : undefined;
143+
const dcItem = node?.DC ? `${i18n('dc')}: ${node.DC}` : undefined;
135144

136-
return <FullNodeViewer node={node} className={b('info')} />;
137-
};
145+
return (
146+
<PageMetaWithAutorefresh
147+
loading={loading}
148+
items={[hostItem, dcItem]}
149+
className={b('meta')}
150+
/>
151+
);
152+
}
153+
154+
interface NodePageTitleProps {
155+
node?: PreparedNode;
156+
}
157+
158+
function NodePageTitle({node}: NodePageTitleProps) {
159+
return (
160+
<EntityPageTitle
161+
entityName={i18n('node')}
162+
status={node?.SystemState}
163+
id={node?.NodeId}
164+
className={b('title')}
165+
/>
166+
);
167+
}
168+
169+
interface NodePageInfoProps {
170+
node?: PreparedNode;
171+
loading?: boolean;
172+
}
173+
174+
function NodePageInfo({node, loading}: NodePageInfoProps) {
175+
if (loading) {
176+
return <InfoViewerSkeleton className={b('info')} rows={10} />;
177+
}
138178

179+
return <FullNodeViewer node={node} className={b('info')} />;
180+
}
181+
182+
interface NodePageContentProps {
183+
nodeId: string;
184+
tenantName?: string;
185+
186+
activeTabId: NodeTab;
187+
tabs: TabsItemProps[];
188+
189+
parentContainer: React.RefObject<HTMLDivElement>;
190+
}
191+
192+
function NodePageContent({
193+
nodeId,
194+
tenantName,
195+
activeTabId,
196+
tabs,
197+
parentContainer,
198+
}: NodePageContentProps) {
139199
const renderTabs = () => {
140200
return (
141201
<div className={b('tabs')}>
142202
<Tabs
143203
size="l"
144-
items={nodeTabs}
145-
activeTab={activeTab.id}
204+
items={tabs}
205+
activeTab={activeTabId}
146206
wrapTo={({id}, tabNode) => {
147207
const path = getDefaultNodePath(
148208
nodeId,
@@ -161,14 +221,14 @@ export function Node() {
161221
};
162222

163223
const renderTabContent = () => {
164-
switch (activeTab.id) {
224+
switch (activeTabId) {
165225
case 'storage': {
166226
return (
167227
<PaginatedStorage
168228
nodeId={nodeId}
169-
parentRef={container}
229+
parentRef={parentContainer}
170230
viewContext={{
171-
nodeId: nodeId?.toString(),
231+
nodeId: nodeId,
172232
}}
173233
/>
174234
);
@@ -186,23 +246,10 @@ export function Node() {
186246
}
187247
};
188248

189-
const renderError = () => {
190-
if (!error) {
191-
return null;
192-
}
193-
194-
return <ResponseError error={error} className={b('error')} />;
195-
};
196-
197249
return (
198-
<div className={b(null)} ref={container}>
199-
{renderHelmet()}
200-
{renderPageMeta()}
201-
{renderPageTitle()}
202-
{renderError()}
203-
{renderInfo()}
250+
<React.Fragment>
204251
{renderTabs()}
205252
{renderTabContent()}
206-
</div>
253+
</React.Fragment>
207254
);
208255
}

0 commit comments

Comments
 (0)