diff --git a/src/components/NodeHostWrapper/NodeHostWrapper.tsx b/src/components/NodeHostWrapper/NodeHostWrapper.tsx index f3dfb8f075..b5634b34e3 100644 --- a/src/components/NodeHostWrapper/NodeHostWrapper.tsx +++ b/src/components/NodeHostWrapper/NodeHostWrapper.tsx @@ -3,7 +3,7 @@ import type {PreparedStorageNode} from '../../store/reducers/storage/types'; import type {NodeAddress} from '../../types/additionalProps'; import type {TNodeInfo, TSystemStateInfo} from '../../types/api/nodes'; import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'; -import {isUnavailableNode} from '../../utils/nodes'; +import {checkIsStorageNode, isUnavailableNode} from '../../utils/nodes'; import {EntityStatus} from '../EntityStatus/EntityStatus'; import {NodeEndpointsTooltipContent} from '../TooltipsContent'; @@ -33,12 +33,17 @@ export const NodeHostWrapper = ({ const isNodeAvailable = !isUnavailableNode(node); + // Storage nodes do not belong to any specific database. + // Including a database in the path would filter data on the node page by that database, + // but for storage nodes this would result in no data being shown. + // Database from node data cannot be used, because we use database ids when uiFactory.useDatabaseId + // https://github.com/ydb-platform/ydb-embedded-ui/issues/3006 + const databaseInPath = checkIsStorageNode(node) ? undefined : (database ?? node.TenantName); + const nodePath = isNodeAvailable ? getDefaultNodePath( {id: node.NodeId, activeTab: node.TenantName ? 'tablets' : 'storage'}, - { - database: database ?? node.TenantName, - }, + {database: databaseInPath}, ) : undefined; diff --git a/src/containers/Node/Node.tsx b/src/containers/Node/Node.tsx index eec30bd049..353f22198d 100644 --- a/src/containers/Node/Node.tsx +++ b/src/containers/Node/Node.tsx @@ -24,6 +24,7 @@ import type {PreparedNode} from '../../store/reducers/node/types'; import {cn} from '../../utils/cn'; import {useAutoRefreshInterval, useTypedDispatch} from '../../utils/hooks'; import {useIsViewerUser} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; +import {checkIsStorageNode} from '../../utils/nodes'; import {useAppTitle} from '../App/AppTitleContext'; import {Configs} from '../Configs/Configs'; import {PaginatedStorage} from '../Storage/PaginatedStorage'; @@ -39,8 +40,6 @@ import './Node.scss'; const b = cn('node'); -const STORAGE_ROLE = 'Storage'; - export function Node() { const container = React.useRef(null); const isViewerUser = useIsViewerUser(); @@ -73,7 +72,7 @@ export function Node() { const pageLoading = isLoading || !capabilitiesLoaded; - const isStorageNode = node?.Roles?.find((el) => el === STORAGE_ROLE); + const isStorageNode = checkIsStorageNode(node); const threadsQuantity = node?.Threads?.length; diff --git a/src/containers/Versions/groupNodes.ts b/src/containers/Versions/groupNodes.ts index a2e9e9b9e1..0477486ab5 100644 --- a/src/containers/Versions/groupNodes.ts +++ b/src/containers/Versions/groupNodes.ts @@ -1,6 +1,7 @@ import groupBy from 'lodash/groupBy'; import type {PreparedStorageNode} from '../../store/reducers/storage/types'; +import {checkIsStorageNode, checkIsTenantNode} from '../../utils/nodes'; import {getColorFromVersionsData, parseNodesToPreparedVersions} from '../../utils/versions'; import type {VersionsDataMap} from '../../utils/versions/types'; @@ -24,7 +25,7 @@ export const getGroupedTenantNodes = ( return Object.keys(dividedByVersion) .map((version) => { - const filteredNodes = dividedByVersion[version].filter(isTenantNode); + const filteredNodes = dividedByVersion[version].filter(checkIsTenantNode); const dividedByTenant = groupBy(filteredNodes, 'Tenants'); const items = Object.keys(dividedByTenant) @@ -49,7 +50,7 @@ export const getGroupedTenantNodes = ( }) .filter((item): item is GroupedNodesItem => Boolean(item)); } else { - const filteredNodes = nodes.filter(isTenantNode); + const filteredNodes = nodes.filter(checkIsTenantNode); const dividedByTenant = groupBy(filteredNodes, 'Tenants'); return Object.keys(dividedByTenant) @@ -92,7 +93,7 @@ export const getGroupedStorageNodes = ( return undefined; } - const storageNodes = nodes.filter(isStorageNode); + const storageNodes = nodes.filter(checkIsStorageNode); const storageNodesDividedByVersion = groupBy(storageNodes, 'Version'); return Object.keys(storageNodesDividedByVersion).map((version) => { @@ -114,7 +115,7 @@ export const getOtherNodes = ( // Nodes that are not included in other groups const otherNodes = nodes.filter( - (node) => !isStorageNode(node) && !isTenantNode(node) && node.Version, + (node) => !checkIsStorageNode(node) && !checkIsTenantNode(node) && node.Version, ); const otherNodesDividedByVersion = groupBy(otherNodes, 'Version'); @@ -126,11 +127,3 @@ export const getOtherNodes = ( }; }); }; - -function isStorageNode(node: PreparedStorageNode) { - return Boolean(node.Roles?.includes('Storage')); -} - -function isTenantNode(node: PreparedStorageNode) { - return Boolean(node.Tenants); -} diff --git a/src/utils/nodes.ts b/src/utils/nodes.ts index ed7442d6ef..26a3c3e495 100644 --- a/src/utils/nodes.ts +++ b/src/utils/nodes.ts @@ -99,3 +99,11 @@ export const getProblemParamValue = (problemFilter: ProblemFilterValue | undefin export const getUptimeParamValue = (nodesUptimeFilter: NodesUptimeFilterValues | undefined) => { return nodesUptimeFilter === NodesUptimeFilterValues.SmallUptime ? HOUR_IN_SECONDS : undefined; }; + +export function checkIsStorageNode(node?: T) { + return Boolean(node?.Roles?.includes('Storage')); +} + +export function checkIsTenantNode(node?: T) { + return Boolean(node?.Tenants); +}