Skip to content

Commit f6ff486

Browse files
committed
fix: better code and buttons
1 parent 7151974 commit f6ff486

File tree

13 files changed

+200
-44
lines changed

13 files changed

+200
-44
lines changed

src/containers/Header/Header.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {clustersApi} from '../../store/reducers/clusters/clusters';
2828
import {tenantApi} from '../../store/reducers/tenant/tenant';
2929
import {uiFactory} from '../../uiFactory/uiFactory';
3030
import {cn} from '../../utils/cn';
31-
import {DEVELOPER_UI_TITLE} from '../../utils/constants';
31+
import {DEVELOPER_UI_TITLE, MONITORING_UI_TITLE} from '../../utils/constants';
3232
import {createDeveloperUIInternalPageHref} from '../../utils/developerUI/developerUI';
3333
import {useTypedSelector} from '../../utils/hooks';
3434
import {
@@ -56,7 +56,7 @@ function Header() {
5656

5757
const isMetaDatabasesAvailable = useDatabasesAvailable();
5858

59-
const {title: clusterTitle} = useClusterBaseInfo();
59+
const {title: clusterTitle, monitoring} = useClusterBaseInfo();
6060

6161
const database = useDatabaseFromQuery();
6262

@@ -93,6 +93,16 @@ function Header() {
9393
const {currentData: databaseData, isLoading: isDatabaseDataLoading} =
9494
tenantApi.useGetTenantInfoQuery(params);
9595

96+
const monitoringLinkUrl =
97+
monitoring && uiFactory.getMonitoringLink && databaseData?.Name && databaseData?.Type
98+
? uiFactory.getMonitoringLink({
99+
monitoring,
100+
clusterName,
101+
dbName: databaseData.Name,
102+
dbType: databaseData.Type,
103+
})
104+
: null;
105+
96106
const breadcrumbItems = React.useMemo(() => {
97107
let options = {
98108
...pageBreadcrumbsOptions,
@@ -128,6 +138,15 @@ function Header() {
128138
}
129139

130140
if (isDatabasePage && database) {
141+
if (monitoringLinkUrl) {
142+
elements.push(
143+
<Button view="flat" href={monitoringLinkUrl} target="_blank">
144+
{MONITORING_UI_TITLE}
145+
<Icon data={ArrowUpRightFromSquare} />
146+
</Button>,
147+
);
148+
}
149+
131150
elements.push(
132151
<Button view={'flat'} onClick={() => getConnectToDBDialog({database})}>
133152
<Icon data={PlugConnection} />

src/containers/Tenant/Diagnostics/Diagnostics.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
height: 100%;
1010

11+
&__tab-badge {
12+
margin-left: var(--g-spacing-2);
13+
}
14+
1115
&__header-wrapper {
1216
padding: 0 var(--g-spacing-5);
1317

src/containers/Tenant/Diagnostics/Diagnostics.tsx

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

3-
import {Tab, TabList, TabProvider} from '@gravity-ui/uikit';
3+
import {TabList, TabProvider} from '@gravity-ui/uikit';
44
import {Helmet} from 'react-helmet-async';
55

66
import {AutoRefreshControl} from '../../../components/AutoRefreshControl/AutoRefreshControl';
77
import {DrawerContextProvider} from '../../../components/Drawer/DrawerContext';
8-
import {InternalLink} from '../../../components/InternalLink';
98
import {
109
useConfigAvailable,
1110
useTopicDataAvailable,
@@ -32,6 +31,7 @@ import {Consumers} from './Consumers';
3231
import Describe from './Describe/Describe';
3332
import DetailedOverview from './DetailedOverview/DetailedOverview';
3433
import {getPagesByType, useDiagnosticsPageLinkGetter} from './DiagnosticsPages';
34+
import {DiagnosticsTabItem} from './DiagnosticsTabItem';
3535
import {HotKeys} from './HotKeys/HotKeys';
3636
import {NetworkWrapper} from './Network/NetworkWrapper';
3737
import {Partitions} from './Partitions/Partitions';
@@ -71,6 +71,7 @@ function Diagnostics({additionalTenantProps}: DiagnosticsProps) {
7171
hasBackups: typeof uiFactory.renderBackups === 'function' && Boolean(controlPlane),
7272
hasConfigs: isViewerUser && hasConfigs,
7373
hasAccess: uiFactory.hasAccess,
74+
hasMonitoring: typeof uiFactory.renderMonitoring === 'function',
7475
databaseType,
7576
});
7677
let activeTab = pages.find((el) => el.id === diagnosticsTab);
@@ -236,16 +237,15 @@ function Diagnostics({additionalTenantProps}: DiagnosticsProps) {
236237
<div className={b('tabs')}>
237238
<TabProvider value={activeTab?.id}>
238239
<TabList size="l">
239-
{pages.map(({id, title}) => {
240-
const linkPath = getDiagnosticsPageLink(id);
241-
return (
242-
<Tab key={id} value={id}>
243-
<InternalLink to={linkPath} as="tab">
244-
{title}
245-
</InternalLink>
246-
</Tab>
247-
);
248-
})}
240+
{pages.map(({id, title, badge}) => (
241+
<DiagnosticsTabItem
242+
key={id}
243+
id={id}
244+
title={title}
245+
linkPath={getDiagnosticsPageLink(id)}
246+
badge={badge}
247+
/>
248+
))}
249249
</TabList>
250250
</TabProvider>
251251
<AutoRefreshControl />

src/containers/Tenant/Diagnostics/DiagnosticsPages.ts

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

3+
import type {LabelProps} from '@gravity-ui/uikit';
34
import {StringParam, useQueryParams} from 'use-query-params';
45

56
import {getTenantPath} from '../../../routes';
67
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
78
import type {TenantDiagnosticsTab} from '../../../store/reducers/tenant/types';
89
import {EPathSubType, EPathType} from '../../../types/api/schema';
910
import type {ETenantType} from '../../../types/api/tenant';
10-
import {uiFactory} from '../../../uiFactory/uiFactory';
1111
import type {TenantQuery} from '../TenantPages';
1212
import {TenantTabsGroups} from '../TenantPages';
1313
import {isDatabaseEntityType, isTopicEntityType} from '../utils/schema';
1414

15+
interface Badge {
16+
text: string;
17+
theme?: LabelProps['theme'];
18+
size?: LabelProps['size'];
19+
}
20+
1521
type Page = {
1622
id: TenantDiagnosticsTab;
1723
title: string;
24+
badge?: Badge;
1825
};
1926

2027
interface GetPagesOptions {
@@ -23,6 +30,7 @@ interface GetPagesOptions {
2330
hasBackups?: boolean;
2431
hasConfigs?: boolean;
2532
hasAccess?: boolean;
33+
hasMonitoring?: boolean;
2634
databaseType?: ETenantType;
2735
}
2836

@@ -114,6 +122,11 @@ const operations = {
114122
const monitoring = {
115123
id: TENANT_DIAGNOSTICS_TABS_IDS.monitoring,
116124
title: 'Monitoring',
125+
badge: {
126+
text: 'New',
127+
theme: 'normal' as const,
128+
size: 'xs' as const,
129+
},
117130
};
118131

119132
const ASYNC_REPLICATION_PAGES = [overview, tablets, describe, access];
@@ -122,6 +135,7 @@ const TRANSFER_PAGES = [overview, tablets, describe, access];
122135

123136
const DATABASE_PAGES = [
124137
overview,
138+
monitoring,
125139
topQueries,
126140
topShards,
127141
nodes,
@@ -137,6 +151,7 @@ const DATABASE_PAGES = [
137151

138152
const SERVERLESS_DATABASE_PAGES = [
139153
overview,
154+
monitoring,
140155
topQueries,
141156
topShards,
142157
tablets,
@@ -226,6 +241,9 @@ function applyFilters(pages: Page[], type?: EPathType, options: GetPagesOptions
226241
if (!options.hasAccess) {
227242
removals.push(TENANT_DIAGNOSTICS_TABS_IDS.access);
228243
}
244+
if (!options.hasMonitoring) {
245+
removals.push(TENANT_DIAGNOSTICS_TABS_IDS.monitoring);
246+
}
229247

230248
return result.filter((p) => !removals.includes(p.id));
231249
}
@@ -241,11 +259,6 @@ export const getPagesByType = (
241259

242260
const result = applyFilters(seeded, type, options);
243261

244-
// Add monitoring tab as second tab if renderMonitoring is available
245-
if (uiFactory.renderMonitoring) {
246-
result.splice(1, 0, monitoring);
247-
}
248-
249262
return result;
250263
};
251264

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type {LabelProps} from '@gravity-ui/uikit';
2+
import {Label, Tab} from '@gravity-ui/uikit';
3+
4+
import {InternalLink} from '../../../components/InternalLink';
5+
import {cn} from '../../../utils/cn';
6+
7+
const b = cn('kv-tenant-diagnostics');
8+
9+
interface DiagnosticsTabItemProps {
10+
id: string;
11+
title: string;
12+
linkPath: string;
13+
badge?: {
14+
text: string;
15+
theme?: LabelProps['theme'];
16+
size?: LabelProps['size'];
17+
};
18+
}
19+
20+
export function DiagnosticsTabItem({id, title, linkPath, badge}: DiagnosticsTabItemProps) {
21+
return (
22+
<Tab key={id} value={id}>
23+
<InternalLink to={linkPath} as="tab">
24+
{title}
25+
{badge && (
26+
<Label className={b('tab-badge')} theme={badge.theme} size={badge.size}>
27+
{badge.text}
28+
</Label>
29+
)}
30+
</InternalLink>
31+
</Tab>
32+
);
33+
}

src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1+
import {DisplayPulse} from '@gravity-ui/icons';
12
import {Button, Flex, HelpMark, Icon, Label} from '@gravity-ui/uikit';
23

34
import {EntityStatus} from '../../../../components/EntityStatus/EntityStatus';
45
import {LoaderWrapper} from '../../../../components/LoaderWrapper/LoaderWrapper';
56
import {QueriesActivityBar} from '../../../../components/QueriesActivityBar/QueriesActivityBar';
67
import {useDatabasesAvailable} from '../../../../store/reducers/capabilities/hooks';
78
import {overviewApi} from '../../../../store/reducers/overview/overview';
8-
import {TENANT_METRICS_TABS_IDS} from '../../../../store/reducers/tenant/constants';
9-
import {tenantApi} from '../../../../store/reducers/tenant/tenant';
9+
import {
10+
TENANT_DIAGNOSTICS_TABS_IDS,
11+
TENANT_METRICS_TABS_IDS,
12+
TENANT_PAGES_IDS,
13+
} from '../../../../store/reducers/tenant/constants';
14+
import {
15+
setDiagnosticsTab,
16+
setTenantPage,
17+
tenantApi,
18+
} from '../../../../store/reducers/tenant/tenant';
1019
import {calculateTenantMetrics} from '../../../../store/reducers/tenants/utils';
1120
import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
12-
import {getDatabaseLinks} from '../../../../utils/additionalProps';
21+
import {uiFactory} from '../../../../uiFactory/uiFactory';
22+
import {getInfoTabLinks} from '../../../../utils/additionalProps';
1323
import {TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
14-
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
24+
import {useAutoRefreshInterval, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
1525
import {useClusterNameFromQuery} from '../../../../utils/hooks/useDatabaseFromQuery';
1626
import {mapDatabaseTypeToDBName} from '../../utils/schema';
1727

@@ -40,6 +50,7 @@ export function TenantOverview({
4050
const {metricsTab} = useTypedSelector((state) => state.tenant);
4151
const [autoRefreshInterval] = useAutoRefreshInterval();
4252
const clusterName = useClusterNameFromQuery();
53+
const dispatch = useTypedDispatch();
4354

4455
const isMetaDatabasesAvailable = useDatabasesAvailable();
4556

@@ -176,28 +187,44 @@ export function TenantOverview({
176187
}
177188
};
178189

179-
const links = getDatabaseLinks(additionalTenantProps, Name, Type);
190+
const links = getInfoTabLinks(additionalTenantProps, Name, Type);
191+
const monitoringTabAvailable = Boolean(uiFactory.renderMonitoring);
192+
193+
const handleOpenMonitoring = () => {
194+
dispatch(setTenantPage(TENANT_PAGES_IDS.diagnostics));
195+
dispatch(setDiagnosticsTab(TENANT_DIAGNOSTICS_TABS_IDS.monitoring));
196+
};
180197

181198
return (
182199
<LoaderWrapper loading={tenantLoading}>
183200
<div className={b()}>
184201
<div className={b('info')}>
185-
<div className={b('top-label')}>{tenantType}</div>
202+
<Flex alignItems="center" gap="2" className={b('top-label')}>
203+
<div>{tenantType}</div>
204+
{monitoringTabAvailable && (
205+
<Button view="normal" onClick={handleOpenMonitoring}>
206+
<Icon data={DisplayPulse} size={16} />
207+
{i18n('action_open-monitoring')}
208+
</Button>
209+
)}
210+
</Flex>
186211
<Flex alignItems="center" gap="1" className={b('top')}>
187212
{renderName()}
188-
<Flex gap="2">
189-
{links.map(({title, url, icon}) => (
190-
<Button
191-
key={title}
192-
href={url}
193-
target="_blank"
194-
size="xs"
195-
title={title}
196-
>
197-
<Icon data={icon} />
198-
</Button>
199-
))}
200-
</Flex>
213+
{links.length > 0 && (
214+
<Flex gap="2">
215+
{links.map(({title, url, icon}) => (
216+
<Button
217+
key={title}
218+
href={url}
219+
target="_blank"
220+
size="xs"
221+
title={title}
222+
>
223+
<Icon data={icon} />
224+
</Button>
225+
))}
226+
</Flex>
227+
)}
201228
</Flex>
202229
<Flex direction="column" gap={4}>
203230
{!isServerless && <HealthcheckPreview database={database} />}

src/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"action_open-monitoring": "Monitoring",
23
"top-nodes.empty-data": "No such nodes",
34
"title_top-nodes-load": "Top nodes by load",
45
"title_top-nodes-pool": "Top nodes by pools usage",

src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {selectIsDirty, selectUserInput} from '../../../../store/reducers/query/q
1414
import {schemaApi} from '../../../../store/reducers/schema/schema';
1515
import {tableSchemaDataApi} from '../../../../store/reducers/tableSchemaData';
1616
import type {EPathType, TEvDescribeSchemeResult} from '../../../../types/api/schema';
17+
import {uiFactory} from '../../../../uiFactory/uiFactory';
1718
import {valueIsDefined} from '../../../../utils';
1819
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
1920
import {getConfirmation} from '../../../../utils/hooks/withConfirmation/useChangeInputWithConfirmation';
@@ -144,6 +145,7 @@ export function SchemaTree(props: SchemaTreeProps) {
144145
getConnectToDBDialog,
145146
schemaData: actionsSchemaData,
146147
isSchemaDataLoading: isActionsDataFetching,
148+
hasMonitoring: typeof uiFactory.renderMonitoring === 'function',
147149
},
148150
databaseFullPath,
149151
database,

src/containers/Tenant/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"actions.connectToDB": "Connect to DB",
2929
"actions.dropIndex": "Drop index",
3030
"actions.openPreview": "Open preview",
31+
"actions.openMonitoring": "Monitoring",
3132
"actions.createTable": "Create table...",
3233
"actions.createExternalTable": "Create external table...",
3334
"actions.createTopic": "Create topic...",

0 commit comments

Comments
 (0)