From 189aa30e455795b3db38b4570e04cd3c75d37e66 Mon Sep 17 00:00:00 2001 From: mufazalov Date: Thu, 28 Aug 2025 10:52:02 +0300 Subject: [PATCH 1/2] fix(Versions): replace radio with sections --- .../NodesTreeTitle/NodesTreeTitle.tsx | 37 ++- src/containers/Versions/Versions.scss | 4 - src/containers/Versions/Versions.tsx | 223 ++++++------------ src/containers/Versions/constants.ts | 17 -- 4 files changed, 106 insertions(+), 175 deletions(-) delete mode 100644 src/containers/Versions/constants.ts diff --git a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx index c3f1fde256..a5fb9a6904 100644 --- a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +++ b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx @@ -1,12 +1,14 @@ import React from 'react'; -import {ChevronDown, ChevronUp, Database} from '@gravity-ui/icons'; -import {ClipboardButton, Flex, Icon, Text} from '@gravity-ui/uikit'; +import {ArrowRight, ChevronDown, ChevronUp, Database} from '@gravity-ui/icons'; +import {Button, ClipboardButton, Flex, Icon, Text} from '@gravity-ui/uikit'; +import {InternalLink} from '../../../components/InternalLink'; import {VersionsBar} from '../../../components/VersionsBar/VersionsBar'; import {cn} from '../../../utils/cn'; import type {PreparedNodeSystemState} from '../../../utils/nodes'; import type {PreparedVersion} from '../../../utils/versions/types'; +import {getTenantPath} from '../../Tenant/TenantPages'; import i18n from '../i18n'; import type {GroupedNodesItem} from '../types'; @@ -59,6 +61,31 @@ export const NodesTreeTitle = ({ } }, [items, nodes]); + const renderNodesCount = () => { + if (isDatabase) { + return ( + + + + ); + } + + return ( + + {i18n('nodes-count', {count: nodesAmount})} + + ); + }; + return (
@@ -77,12 +104,10 @@ export const NodesTreeTitle = ({ /> ) : null} - - {i18n('nodes-count', {count: nodesAmount})} - + {renderNodesCount()} - {preparedVersions ? ( + {isDatabase && preparedVersions ? (
diff --git a/src/containers/Versions/Versions.scss b/src/containers/Versions/Versions.scss index ab6cd9a409..e3216caf5a 100644 --- a/src/containers/Versions/Versions.scss +++ b/src/containers/Versions/Versions.scss @@ -9,11 +9,7 @@ font-size: var(--ydb-info-viewer-font-size); line-height: var(--ydb-info-viewer-line-height); - &__controls { - margin-bottom: var(--g-spacing-3); - } &__overall { margin-top: var(--g-spacing-4); - margin-bottom: var(--g-spacing-6); } } diff --git a/src/containers/Versions/Versions.tsx b/src/containers/Versions/Versions.tsx index 28d6037112..f72460b015 100644 --- a/src/containers/Versions/Versions.tsx +++ b/src/containers/Versions/Versions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {ChevronsCollapseVertical, ChevronsExpandVertical} from '@gravity-ui/icons'; -import {Button, Flex, Icon, SegmentedRadioGroup, Select, Text} from '@gravity-ui/uikit'; +import {Button, Flex, Icon, Select, Text} from '@gravity-ui/uikit'; import {StringParam, useQueryParams} from 'use-query-params'; import {z} from 'zod'; @@ -15,10 +15,9 @@ import {useAutoRefreshInterval} from '../../utils/hooks'; import type {PreparedVersion, VersionsDataMap} from '../../utils/versions/types'; import {GroupedNodesTree} from './GroupedNodesTree/GroupedNodesTree'; -import type {NodeType} from './constants'; -import {NODE_TYPES, NODE_TYPES_TITLE} from './constants'; import {getGroupedStorageNodes, getGroupedTenantNodes, getOtherNodes} from './groupNodes'; import i18n from './i18n'; +import type {GroupedNodesItem} from './types'; import {GroupByValue} from './types'; import {useGetPreparedVersions, useVersionsDataMap} from './utils'; @@ -62,20 +61,15 @@ interface VersionsProps { versionsDataMap?: VersionsDataMap; } -const nodeTypeSchema = z.nativeEnum(NODE_TYPES).catch(NODE_TYPES.storage); const groupByValueSchema = z.nativeEnum(GroupByValue).catch(GroupByValue.VERSION); function Versions({preparedVersions, nodes, versionsDataMap}: VersionsProps) { - const [{nodeType: rawNodeType, groupBy: rawGroupByValue}, setQueryParams] = useQueryParams({ - nodeType: StringParam, + const [{groupBy: rawGroupByValue}, setQueryParams] = useQueryParams({ groupBy: StringParam, }); - const nodeType = nodeTypeSchema.parse(rawNodeType); const groupByValue = groupByValueSchema.parse(rawGroupByValue); - const [expanded, setExpanded] = React.useState(false); - const tenantNodes = React.useMemo(() => { return getGroupedTenantNodes(nodes, versionsDataMap, groupByValue); }, [groupByValue, nodes, versionsDataMap]); @@ -89,167 +83,100 @@ function Versions({preparedVersions, nodes, versionsDataMap}: VersionsProps) { const handleGroupByValueChange = (value: string) => { setQueryParams({groupBy: value as GroupByValue}, 'replaceIn'); }; - const handleNodeTypeChange = (value: string) => { - setQueryParams({nodeType: value as NodeType}, 'replaceIn'); - }; - const renderExpandButton = () => { + const renderGroupControl = () => { + const options = [ + {value: GroupByValue.TENANT, content: i18n('title_database')}, + {value: GroupByValue.VERSION, content: i18n('title_version')}, + ]; return ( - + handleGroupByValueChange(values[0])} - width={200} - size="m" - /> - ); - } + if (!nodes?.length) { return null; - }; - const renderControls = () => { + } + + const renderExpandButton = () => { return ( - - {renderNodeTypeRadio()} - {renderGroupControl()} - {renderExpandButton()} - + ); }; - const renderStorageNodes = () => { - if (storageNodes?.length) { - return storageNodes.map(({title, nodes: itemNodes, items, versionColor}) => ( + const renderNodes = () => { + return nodes.map( + ({ + title, + isDatabase, + nodes: itemNodes, + items, + versionColor, + preparedVersions: nodesVersions, + }) => ( - )); - } - return null; - }; - const renderDatabaseNodes = () => { - if (tenantNodes?.length) { - return tenantNodes.map( - ({ - title, - isDatabase, - nodes: itemNodes, - items, - versionColor, - preparedVersions: nodesVersions, - }) => ( - - ), - ); - } - return null; - }; - - const renderOtherNodes = () => { - if (otherNodes?.length) { - return otherNodes.map( - ({ - title, - nodes: itemNodes, - items, - versionColor, - preparedVersions: nodesVersions, - }) => ( - - ), - ); - } - return null; - }; - - const renderContent = () => { - switch (nodeType) { - case NODE_TYPES.storage: - return renderStorageNodes(); - case NODE_TYPES.database: - return renderDatabaseNodes(); - case NODE_TYPES.other: - return renderOtherNodes(); - default: - return null; - } + ), + ); }; - const overallContent = ( - - {i18n('title_overall')} - - - ); - return ( -
- {overallContent} - {renderControls()} - - {renderContent()} + + + + {sectionTitle} + {renderControls?.()} + + {renderExpandButton()} -
+ {renderNodes()} +
); } diff --git a/src/containers/Versions/constants.ts b/src/containers/Versions/constants.ts deleted file mode 100644 index 7a025a0274..0000000000 --- a/src/containers/Versions/constants.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type {ValueOf} from '../../types/common'; - -import i18n from './i18n'; - -export const NODE_TYPES = { - storage: 'storage', - database: 'database', - other: 'other', -}; - -export type NodeType = ValueOf; - -export const NODE_TYPES_TITLE = { - [NODE_TYPES.storage]: i18n('title_storage-nodes'), - [NODE_TYPES.database]: i18n('title_database-nodes'), - [NODE_TYPES.other]: i18n('title_other-nodes'), -}; From 728e896a1869479ecb4a33aab697d055de21f3f6 Mon Sep 17 00:00:00 2001 From: mufazalov Date: Fri, 29 Aug 2025 13:28:41 +0300 Subject: [PATCH 2/2] fix: do not wrap button with a link --- .../NodesTreeTitle/NodesTreeTitle.tsx | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx index a5fb9a6904..aae87329be 100644 --- a/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +++ b/src/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx @@ -2,8 +2,8 @@ import React from 'react'; import {ArrowRight, ChevronDown, ChevronUp, Database} from '@gravity-ui/icons'; import {Button, ClipboardButton, Flex, Icon, Text} from '@gravity-ui/uikit'; +import {useHistory} from 'react-router-dom'; -import {InternalLink} from '../../../components/InternalLink'; import {VersionsBar} from '../../../components/VersionsBar/VersionsBar'; import {cn} from '../../../utils/cn'; import type {PreparedNodeSystemState} from '../../../utils/nodes'; @@ -37,6 +37,8 @@ export const NodesTreeTitle = ({ preparedVersions, onClick, }: NodesTreeTitleProps) => { + const history = useHistory(); + const handleClick = React.useCallback>( (event) => { const shouldSkip = event.nativeEvent.composedPath().some(isActiveButtonTarget); @@ -64,18 +66,15 @@ export const NodesTreeTitle = ({ const renderNodesCount = () => { if (isDatabase) { return ( - + history.push(getTenantPath({database: title, diagnosticsTab: 'nodes'})) + } > - - + {i18n('nodes-count', {count: nodesAmount})} + + ); }