From ac89a5a8f53161c3c59723cf618c077fbc495357 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Tue, 25 Feb 2025 17:35:07 +0300 Subject: [PATCH] fix: if database pass name to query params and to backend handlers --- .../NodeHostWrapper/NodeHostWrapper.tsx | 8 +-- src/components/PDiskInfo/PDiskInfo.tsx | 8 ++- src/components/PDiskPopup/PDiskPopup.tsx | 8 ++- .../TabletNameWrapper/TabletNameWrapper.tsx | 7 ++- src/components/VDisk/VDisk.tsx | 4 +- src/components/VDisk/utils.ts | 5 +- src/components/VDiskInfo/VDiskInfo.tsx | 5 +- src/components/VDiskPopup/VDiskPopup.tsx | 32 +++++++--- src/containers/Header/Header.tsx | 6 +- src/containers/Node/Node.tsx | 2 +- src/containers/PDiskPage/PDiskPage.tsx | 10 +++- .../PDiskSpaceDistribution.tsx | 4 +- src/containers/Storage/PDisk/PDisk.tsx | 4 +- .../Storage/PaginatedStorageNodes.tsx | 17 +----- .../Storage/StorageGroups/columns/columns.tsx | 15 +++-- .../Storage/StorageGroups/columns/hooks.ts | 6 +- .../PaginatedStorageNodesTable.tsx | 4 +- .../Storage/StorageNodes/columns/columns.tsx | 14 ++++- .../Storage/StorageNodes/columns/hooks.ts | 3 +- .../Storage/StorageNodes/columns/types.ts | 1 - .../StorageGroupPage/StorageGroupPage.tsx | 5 +- .../components/TabletInfo/TabletInfo.tsx | 15 +++-- .../components/TabletTable/TabletTable.tsx | 12 +++- src/containers/Tablets/TabletsTable.tsx | 6 +- .../Tenant/Diagnostics/Diagnostics.tsx | 1 + .../Tenant/Diagnostics/Network/Network.tsx | 4 +- .../Partitions/columns/columns.tsx | 17 +++--- .../utils/useGetPartitionsColumns.ts | 12 ++-- .../Diagnostics/TopShards/TopShards.tsx | 6 +- .../Diagnostics/TopShards/columns/columns.tsx | 18 ++++-- src/containers/VDiskPage/VDiskPage.tsx | 7 ++- src/routes.ts | 6 ++ src/services/api/pdisk.ts | 7 ++- src/services/api/viewer.ts | 17 +++++- .../reducers/capabilities/capabilities.ts | 2 +- src/store/reducers/node/node.ts | 4 +- src/store/reducers/pdisk/pdisk.ts | 17 ++++-- src/store/reducers/vdisk/vdisk.ts | 18 ++++-- .../developerUI/__test__/developerUI.test.ts | 5 +- src/utils/developerUI/developerUI.ts | 60 +++++++++++++++---- src/utils/hooks/useNodeDeveloperUIHref.ts | 4 +- 41 files changed, 286 insertions(+), 120 deletions(-) diff --git a/src/components/NodeHostWrapper/NodeHostWrapper.tsx b/src/components/NodeHostWrapper/NodeHostWrapper.tsx index 2a9e18d0d..c14429213 100644 --- a/src/components/NodeHostWrapper/NodeHostWrapper.tsx +++ b/src/components/NodeHostWrapper/NodeHostWrapper.tsx @@ -4,8 +4,8 @@ import {getDefaultNodePath} from '../../containers/Node/NodePages'; import type {NodeAddress} from '../../types/additionalProps'; import type {TNodeInfo, TSystemStateInfo} from '../../types/api/nodes'; import { + createBaseDeveloperUILinkWithNodeId, createDeveloperUIInternalPageHref, - createDeveloperUILinkWithNodeId, } from '../../utils/developerUI/developerUI'; import {isUnavailableNode} from '../../utils/nodes'; import {CellWithPopover} from '../CellWithPopover/CellWithPopover'; @@ -46,11 +46,11 @@ export const NodeHostWrapper = ({ if (getNodeRef) { const developerUIHref = getNodeRef(node); developerUIInternalHref = developerUIHref - ? createDeveloperUIInternalPageHref(developerUIHref) + ? createDeveloperUIInternalPageHref(developerUIHref, database) : undefined; } else if (node.NodeId) { - const developerUIHref = createDeveloperUILinkWithNodeId(node.NodeId); - developerUIInternalHref = createDeveloperUIInternalPageHref(developerUIHref); + const developerUIHref = createBaseDeveloperUILinkWithNodeId(node.NodeId); + developerUIInternalHref = createDeveloperUIInternalPageHref(developerUIHref, database); } const nodePath = isNodeAvailable diff --git a/src/components/PDiskInfo/PDiskInfo.tsx b/src/components/PDiskInfo/PDiskInfo.tsx index 676b1210c..0d2ab63be 100644 --- a/src/components/PDiskInfo/PDiskInfo.tsx +++ b/src/components/PDiskInfo/PDiskInfo.tsx @@ -7,6 +7,7 @@ import {cn} from '../../utils/cn'; import {formatStorageValuesToGb} from '../../utils/dataFormatters/dataFormatters'; import {createPDiskDeveloperUILink} from '../../utils/developerUI/developerUI'; import type {PreparedPDisk} from '../../utils/disks/types'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import type {InfoViewerItem} from '../InfoViewer'; import {InfoViewer} from '../InfoViewer/InfoViewer'; @@ -25,6 +26,7 @@ interface GetPDiskInfoOptions { nodeId?: number | string | null; withPDiskPageLink?: boolean; isUserAllowedToMakeChanges?: boolean; + database?: string; } // eslint-disable-next-line complexity @@ -33,6 +35,7 @@ function getPDiskInfo({ nodeId, withPDiskPageLink, isUserAllowedToMakeChanges, + database, }: GetPDiskInfoOptions) { const { PDiskId, @@ -147,10 +150,11 @@ function getPDiskInfo({ valueIsDefined(nodeId); if (shouldDisplayLinks) { - const pDiskPagePath = getPDiskPagePath(PDiskId, nodeId); + const pDiskPagePath = getPDiskPagePath(PDiskId, nodeId, {database}); const pDiskInternalViewerPath = createPDiskDeveloperUILink({ nodeId, pDiskId: PDiskId, + database, }); additionalInfo.push({ @@ -189,12 +193,14 @@ export function PDiskInfo({ className, }: PDiskInfoProps) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const database = useDatabaseFromQuery(); const [generalInfo, statusInfo, spaceInfo, additionalInfo] = getPDiskInfo({ pDisk, nodeId, withPDiskPageLink, isUserAllowedToMakeChanges, + database, }); return ( diff --git a/src/components/PDiskPopup/PDiskPopup.tsx b/src/components/PDiskPopup/PDiskPopup.tsx index 886451879..eef919562 100644 --- a/src/components/PDiskPopup/PDiskPopup.tsx +++ b/src/components/PDiskPopup/PDiskPopup.tsx @@ -7,6 +7,7 @@ import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'; import {createPDiskDeveloperUILink} from '../../utils/developerUI/developerUI'; import type {PreparedPDisk} from '../../utils/disks/types'; import {useTypedSelector} from '../../utils/hooks'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {bytesToGB, isNumeric} from '../../utils/utils'; import {InfoViewer} from '../InfoViewer'; @@ -19,6 +20,7 @@ export const preparePDiskData = ( data: PreparedPDisk, nodeData?: {Host?: string; DC?: string}, withDeveloperUILink?: boolean, + database?: string, ) => { const { AvailableSize, @@ -76,6 +78,7 @@ export const preparePDiskData = ( const pDiskInternalViewerPath = createPDiskDeveloperUILink({ nodeId: NodeId, pDiskId: PDiskId, + database, }); pdiskData.push({ @@ -92,12 +95,13 @@ interface PDiskPopupProps { } export const PDiskPopup = ({data}: PDiskPopupProps) => { + const database = useDatabaseFromQuery(); const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); const nodesMap = useTypedSelector(selectNodesMap); const nodeData = valueIsDefined(data.NodeId) ? nodesMap?.get(data.NodeId) : undefined; const info = React.useMemo( - () => preparePDiskData(data, nodeData, isUserAllowedToMakeChanges), - [data, nodeData, isUserAllowedToMakeChanges], + () => preparePDiskData(data, nodeData, isUserAllowedToMakeChanges, database), + [data, nodeData, isUserAllowedToMakeChanges, database], ); return ; diff --git a/src/components/TabletNameWrapper/TabletNameWrapper.tsx b/src/components/TabletNameWrapper/TabletNameWrapper.tsx index f3bf697c3..067d9ada4 100644 --- a/src/components/TabletNameWrapper/TabletNameWrapper.tsx +++ b/src/components/TabletNameWrapper/TabletNameWrapper.tsx @@ -2,6 +2,7 @@ import {DefinitionList, PopoverBehavior} from '@gravity-ui/uikit'; import {getTabletPagePath} from '../../routes'; import {createTabletDeveloperUIHref} from '../../utils/developerUI/developerUI'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {CellWithPopover} from '../CellWithPopover/CellWithPopover'; import {EntityStatus} from '../EntityStatus/EntityStatus'; @@ -11,11 +12,11 @@ import i18n from './i18n'; interface TabletNameWrapperProps { tabletId: string | number; - database?: string; } -export function TabletNameWrapper({tabletId, database}: TabletNameWrapperProps) { +export function TabletNameWrapper({tabletId}: TabletNameWrapperProps) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const database = useDatabaseFromQuery(); const tabletPath = getTabletPagePath(tabletId, {database}); @@ -28,7 +29,7 @@ export function TabletNameWrapper({tabletId, database}: TabletNameWrapperProps) diff --git a/src/components/VDisk/VDisk.tsx b/src/components/VDisk/VDisk.tsx index 700330ae5..c9d0fedc1 100644 --- a/src/components/VDisk/VDisk.tsx +++ b/src/components/VDisk/VDisk.tsx @@ -1,5 +1,6 @@ import {cn} from '../../utils/cn'; import type {PreparedVDisk} from '../../utils/disks/types'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {DiskStateProgressBar} from '../DiskStateProgressBar/DiskStateProgressBar'; import {HoverPopup} from '../HoverPopup/HoverPopup'; import {InternalLink} from '../InternalLink'; @@ -34,7 +35,8 @@ export const VDisk = ({ delayClose, delayOpen, }: VDiskProps) => { - const vDiskPath = getVDiskLink(data); + const database = useDatabaseFromQuery(); + const vDiskPath = getVDiskLink(data, database); return ( ({ ...infoViewerProps }: VDiskInfoProps) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const database = useDatabaseFromQuery(); const { AllocatedSize, @@ -152,7 +154,7 @@ export function VDiskInfo({ const links: React.ReactNode[] = []; if (withVDiskPageLink) { - const vDiskPagePath = getVDiskPagePath(VDiskSlotId, PDiskId, NodeId); + const vDiskPagePath = getVDiskPagePath(VDiskSlotId, PDiskId, NodeId, {database}); links.push( ({ nodeId: NodeId, pDiskId: PDiskId, vDiskSlotId: VDiskSlotId, + database, }); links.push( diff --git a/src/components/VDiskPopup/VDiskPopup.tsx b/src/components/VDiskPopup/VDiskPopup.tsx index 5f983a0a9..14dd64d1d 100644 --- a/src/components/VDiskPopup/VDiskPopup.tsx +++ b/src/components/VDiskPopup/VDiskPopup.tsx @@ -11,6 +11,7 @@ import {createVDiskDeveloperUILink} from '../../utils/developerUI/developerUI'; import {isFullVDiskData} from '../../utils/disks/helpers'; import type {PreparedVDisk, UnavailableDonor} from '../../utils/disks/types'; import {useTypedSelector} from '../../utils/hooks'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {bytesToGB, bytesToSpeed} from '../../utils/utils'; import type {InfoViewerItem} from '../InfoViewer'; @@ -24,7 +25,11 @@ import './VDiskPopup.scss'; const b = cn('vdisk-storage-popup'); -const prepareUnavailableVDiskData = (data: UnavailableDonor, withDeveloperUILink?: boolean) => { +const prepareUnavailableVDiskData = ( + data: UnavailableDonor, + withDeveloperUILink?: boolean, + database?: string, +) => { const {NodeId, PDiskId, VSlotId, StoragePoolName} = data; const vdiskData: InfoViewerItem[] = [{label: 'State', value: 'not available'}]; @@ -49,6 +54,7 @@ const prepareUnavailableVDiskData = (data: UnavailableDonor, withDeveloperUILink nodeId: NodeId, pDiskId: PDiskId, vDiskSlotId: VSlotId, + database, }); vdiskData.push({ @@ -61,7 +67,11 @@ const prepareUnavailableVDiskData = (data: UnavailableDonor, withDeveloperUILink }; // eslint-disable-next-line complexity -const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => { +const prepareVDiskData = ( + data: PreparedVDisk, + withDeveloperUILink?: boolean, + database?: string, +) => { const { NodeId, PDiskId, @@ -160,6 +170,7 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => nodeId: NodeId, pDiskId: PDiskId, vDiskSlotId: VDiskSlotId, + database, }); vdiskData.push({ @@ -176,6 +187,7 @@ interface VDiskPopupProps { } export const VDiskPopup = ({data}: VDiskPopupProps) => { + const database = useDatabaseFromQuery(); const isFullData = isFullVDiskData(data); const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); @@ -183,9 +195,9 @@ export const VDiskPopup = ({data}: VDiskPopupProps) => { const vdiskInfo = React.useMemo( () => isFullData - ? prepareVDiskData(data, isUserAllowedToMakeChanges) - : prepareUnavailableVDiskData(data, isUserAllowedToMakeChanges), - [data, isFullData, isUserAllowedToMakeChanges], + ? prepareVDiskData(data, isUserAllowedToMakeChanges, database) + : prepareUnavailableVDiskData(data, isUserAllowedToMakeChanges, database), + [data, isFullData, isUserAllowedToMakeChanges, database], ); const nodesMap = useTypedSelector(selectNodesMap); @@ -194,8 +206,8 @@ export const VDiskPopup = ({data}: VDiskPopupProps) => { () => isFullData && data.PDisk && - preparePDiskData(data.PDisk, nodeData, isUserAllowedToMakeChanges), - [data, nodeData, isFullData, isUserAllowedToMakeChanges], + preparePDiskData(data.PDisk, nodeData, isUserAllowedToMakeChanges, database), + [data, nodeData, isFullData, isUserAllowedToMakeChanges, database], ); const donorsInfo: InfoViewerItem[] = []; @@ -204,7 +216,11 @@ export const VDiskPopup = ({data}: VDiskPopupProps) => { for (const donor of donors) { donorsInfo.push({ label: 'VDisk', - value: {donor.StringifiedId}, + value: ( + + {donor.StringifiedId} + + ), }); } } diff --git a/src/containers/Header/Header.tsx b/src/containers/Header/Header.tsx index 7ddae7f9d..33a29d560 100644 --- a/src/containers/Header/Header.tsx +++ b/src/containers/Header/Header.tsx @@ -74,7 +74,11 @@ function Header({mainPage}: HeaderProps) { if (isUserAllowedToMakeChanges) { elements.push( - , diff --git a/src/containers/Node/Node.tsx b/src/containers/Node/Node.tsx index 778e19c30..d354a4935 100644 --- a/src/containers/Node/Node.tsx +++ b/src/containers/Node/Node.tsx @@ -53,7 +53,7 @@ export function Node() { const [autoRefreshInterval] = useAutoRefreshInterval(); - const params = nodeId ? {nodeId} : skipToken; + const params = nodeId ? {nodeId, database: tenantNameFromQuery?.toString()} : skipToken; const { currentData: node, isLoading, diff --git a/src/containers/PDiskPage/PDiskPage.tsx b/src/containers/PDiskPage/PDiskPage.tsx index d7efbbfd8..82464f722 100644 --- a/src/containers/PDiskPage/PDiskPage.tsx +++ b/src/containers/PDiskPage/PDiskPage.tsx @@ -24,6 +24,7 @@ import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; import {getPDiskId, getSeverityColor} from '../../utils/disks/helpers'; import {useAutoRefreshInterval, useTypedDispatch} from '../../utils/hooks'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {PaginatedStorage} from '../Storage/PaginatedStorage'; @@ -65,6 +66,8 @@ export function PDiskPage() { const newDiskApiAvailable = useDiskPagesAvailable(); const containerRef = React.useRef(null); + const database = useDatabaseFromQuery(); + const [{nodeId, pDiskId, activeTab}] = useQueryParams({ activeTab: StringParam, nodeId: StringParam, @@ -80,7 +83,7 @@ export function PDiskPage() { }, [dispatch, nodeId, pDiskId]); const [autoRefreshInterval] = useAutoRefreshInterval(); - const params = pDiskParamsDefined ? {nodeId, pDiskId} : skipToken; + const params = pDiskParamsDefined ? {nodeId, pDiskId, database} : skipToken; const pdiskDataQuery = pDiskApi.useGetPdiskInfoQuery(params, { pollingInterval: autoRefreshInterval, }); @@ -222,7 +225,7 @@ export function PDiskPage() { activeTab={pDiskTab} wrapTo={({id}, tabNode) => { const path = pDiskParamsDefined - ? getPDiskPagePath(pDiskId, nodeId, {activeTab: id}) + ? getPDiskPagePath(pDiskId, nodeId, {activeTab: id, database}) : undefined; return ( @@ -240,13 +243,14 @@ export function PDiskPage() { case 'spaceDistribution': { return pDiskData ? (
- +
) : null; } case 'storage': { return pDiskParamsDefined ? ( { } function Slot({item, pDiskId, nodeId}: SlotProps) { + const database = useDatabaseFromQuery(); const renderContent = () => { if (isVDiskSlot(item)) { const vDiskPagePath = valueIsDefined(item.SlotData?.VDiskSlotId) && valueIsDefined(pDiskId) && valueIsDefined(nodeId) - ? getVDiskPagePath(item.SlotData.VDiskSlotId, pDiskId, nodeId) + ? getVDiskPagePath(item.SlotData.VDiskSlotId, pDiskId, nodeId, {database}) : undefined; return ( diff --git a/src/containers/Storage/PDisk/PDisk.tsx b/src/containers/Storage/PDisk/PDisk.tsx index 2609607ed..7f3a0a22e 100644 --- a/src/containers/Storage/PDisk/PDisk.tsx +++ b/src/containers/Storage/PDisk/PDisk.tsx @@ -9,6 +9,7 @@ import {getPDiskPagePath} from '../../../routes'; import {valueIsDefined} from '../../../utils'; import {cn} from '../../../utils/cn'; import type {PreparedPDisk, PreparedVDisk} from '../../../utils/disks/types'; +import {useDatabaseFromQuery} from '../../../utils/hooks/useDatabaseFromQuery'; import type {StorageViewContext} from '../types'; import {isVdiskActive} from '../utils'; @@ -37,6 +38,7 @@ export const PDisk = ({ progressBarClassName, viewContext, }: PDiskProps) => { + const database = useDatabaseFromQuery(); const {NodeId, PDiskId} = data; const pDiskIdsDefined = valueIsDefined(NodeId) && valueIsDefined(PDiskId); @@ -75,7 +77,7 @@ export const PDisk = ({ let pDiskPath: string | undefined; if (pDiskIdsDefined) { - pDiskPath = getPDiskPagePath(PDiskId, NodeId); + pDiskPath = getPDiskPagePath(PDiskId, NodeId, {database}); } return ( diff --git a/src/containers/Storage/PaginatedStorageNodes.tsx b/src/containers/Storage/PaginatedStorageNodes.tsx index d67721894..f8fd5d946 100644 --- a/src/containers/Storage/PaginatedStorageNodes.tsx +++ b/src/containers/Storage/PaginatedStorageNodes.tsx @@ -11,6 +11,7 @@ import { import {useClusterBaseInfo} from '../../store/reducers/cluster/cluster'; import {storageApi} from '../../store/reducers/storage/storage'; import {useAutoRefreshInterval} from '../../utils/hooks'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {NodesUptimeFilterValues} from '../../utils/nodes'; import {useAdditionalNodeProps} from '../AppWithClusters/useClusterData'; @@ -57,7 +58,6 @@ export const PaginatedStorageNodes = (props: PaginatedStorageProps) => { }; function StorageNodesComponent({ - database, nodeId, groupId, viewContext, @@ -70,7 +70,6 @@ function StorageNodesComponent({ const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping(); const {columnsToShow, columnsToSelect, setColumns} = useStorageNodesColumnsToSelect({ - database, viewContext, }); @@ -90,7 +89,6 @@ function StorageNodesComponent({ return ( ({ name: STORAGE_GROUPS_COLUMNS_IDS.GroupId, header: STORAGE_GROUPS_COLUMNS_TITLES.GroupId, width: 130, render: ({row}) => { return row.GroupId ? ( - + {row.GroupId} ) : ( @@ -156,7 +159,7 @@ const groupIdColumn: StorageGroupsColumn = { }, sortAccessor: (row) => Number(row.GroupId), align: DataTable.RIGHT, -}; +}); const usedColumn: StorageGroupsColumn = { name: STORAGE_GROUPS_COLUMNS_IDS.Used, @@ -264,9 +267,9 @@ const getDisksColumn = (data?: GetStorageColumnsData): StorageGroupsColumn => ({ sortable: false, }); -export const getStorageTopGroupsColumns: StorageColumnsGetter = () => { +export const getStorageTopGroupsColumns: StorageColumnsGetter = (data) => { const columns = [ - groupIdColumn, + getGroupIdColumn(data), typeColumn, erasureColumn, usageColumn, @@ -284,7 +287,7 @@ export const getStorageTopGroupsColumns: StorageColumnsGetter = () => { export const getStorageGroupsColumns: StorageColumnsGetter = (data) => { const columns = [ - groupIdColumn, + getGroupIdColumn(data), poolNameColumn, typeColumn, erasureColumn, diff --git a/src/containers/Storage/StorageGroups/columns/hooks.ts b/src/containers/Storage/StorageGroups/columns/hooks.ts index bcb422ba3..fa261475c 100644 --- a/src/containers/Storage/StorageGroups/columns/hooks.ts +++ b/src/containers/Storage/StorageGroups/columns/hooks.ts @@ -1,6 +1,7 @@ import React from 'react'; import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants'; +import {useDatabaseFromQuery} from '../../../../utils/hooks/useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from '../../../../utils/hooks/useIsUserAllowedToMakeChanges'; import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns'; @@ -20,15 +21,16 @@ export function useStorageGroupsSelectedColumns({ viewContext, }: GetStorageGroupsColumnsParams) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const database = useDatabaseFromQuery(); const columns = React.useMemo(() => { - const allColumns = getStorageGroupsColumns({viewContext}); + const allColumns = getStorageGroupsColumns({viewContext, database}); if (isUserAllowedToMakeChanges) { return allColumns; } return allColumns.filter((column) => !isMonitoringUserGroupsColumn(column.name)); - }, [isUserAllowedToMakeChanges, viewContext]); + }, [isUserAllowedToMakeChanges, viewContext, database]); const requiredColumns = React.useMemo(() => { if (visibleEntities === VISIBLE_ENTITIES.missing) { diff --git a/src/containers/Storage/StorageNodes/PaginatedStorageNodesTable.tsx b/src/containers/Storage/StorageNodes/PaginatedStorageNodesTable.tsx index 1bc29e6f8..67349ded9 100644 --- a/src/containers/Storage/StorageNodes/PaginatedStorageNodesTable.tsx +++ b/src/containers/Storage/StorageNodes/PaginatedStorageNodesTable.tsx @@ -6,6 +6,7 @@ import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants'; import type {PreparedStorageNode, VisibleEntities} from '../../../store/reducers/storage/types'; import type {NodesGroupByField} from '../../../types/api/nodes'; import {cn} from '../../../utils/cn'; +import {useDatabaseFromQuery} from '../../../utils/hooks/useDatabaseFromQuery'; import {NodesUptimeFilterValues, isUnavailableNode} from '../../../utils/nodes'; import {StorageNodesEmptyDataMessage} from './StorageNodesEmptyDataMessage'; @@ -24,7 +25,6 @@ const getRowUnavailableClassName = (row: PreparedStorageNode) => interface PaginatedStorageNodesTableProps { columns: StorageNodesColumn[]; - database?: string; nodeId?: string | number; groupId?: string | number; @@ -44,7 +44,6 @@ interface PaginatedStorageNodesTableProps { export const PaginatedStorageNodesTable = ({ columns, - database, nodeId, groupId, filterGroup, @@ -58,6 +57,7 @@ export const PaginatedStorageNodesTable = ({ renderErrorMessage, initialEntitiesCount, }: PaginatedStorageNodesTableProps) => { + const database = useDatabaseFromQuery(); const tableFilters = React.useMemo(() => { return { searchValue, diff --git a/src/containers/Storage/StorageNodes/columns/columns.tsx b/src/containers/Storage/StorageNodes/columns/columns.tsx index 6200092e3..25b0d31a3 100644 --- a/src/containers/Storage/StorageNodes/columns/columns.tsx +++ b/src/containers/Storage/StorageNodes/columns/columns.tsx @@ -33,7 +33,10 @@ const b = cn('ydb-storage-nodes-columns'); const MAX_SLOTS_CSS_VAR = '--maximum-slots'; const MAX_DISKS_CSS_VAR = '--maximum-disks'; -const getPDisksColumn = ({viewContext}: GetStorageNodesColumnsParams): StorageNodesColumn => { +const getPDisksColumn = ({ + viewContext, + database, +}: GetStorageNodesColumnsParams): StorageNodesColumn => { return { name: NODES_COLUMNS_IDS.PDisks, header: NODES_COLUMNS_TITLES.PDisks, @@ -53,7 +56,12 @@ const getPDisksColumn = ({viewContext}: GetStorageNodesColumnsParams): StorageNo return (
- +
); })} @@ -87,7 +95,7 @@ export const getStorageNodesColumns = ({ getDiskSpaceUsageColumn(), getVersionColumn(), getMissingDisksColumn(), - getPDisksColumn({viewContext}), + getPDisksColumn({viewContext, database}), ]; const sortableColumns = columns.map((column) => ({ diff --git a/src/containers/Storage/StorageNodes/columns/hooks.ts b/src/containers/Storage/StorageNodes/columns/hooks.ts index 9f05a4aa3..79e849959 100644 --- a/src/containers/Storage/StorageNodes/columns/hooks.ts +++ b/src/containers/Storage/StorageNodes/columns/hooks.ts @@ -5,6 +5,7 @@ import { NODES_COLUMNS_TITLES, } from '../../../../components/nodesColumns/constants'; import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants'; +import {useDatabaseFromQuery} from '../../../../utils/hooks/useDatabaseFromQuery'; import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns'; import {getStorageNodesColumns} from './columns'; @@ -17,10 +18,10 @@ import type {GetStorageNodesColumnsParams} from './types'; export function useStorageNodesSelectedColumns({ visibleEntities, - database, additionalNodesProps, viewContext, }: GetStorageNodesColumnsParams) { + const database = useDatabaseFromQuery(); const columns = React.useMemo(() => { return getStorageNodesColumns({database, additionalNodesProps, viewContext}); }, [database, additionalNodesProps, viewContext]); diff --git a/src/containers/Storage/StorageNodes/columns/types.ts b/src/containers/Storage/StorageNodes/columns/types.ts index e144c5957..4424bfc67 100644 --- a/src/containers/Storage/StorageNodes/columns/types.ts +++ b/src/containers/Storage/StorageNodes/columns/types.ts @@ -8,6 +8,5 @@ export type StorageNodesColumn = Column; export interface GetStorageNodesColumnsParams { additionalNodesProps?: AdditionalNodesProps | undefined; visibleEntities?: VisibleEntities; - database?: string; viewContext?: StorageViewContext; } diff --git a/src/containers/StorageGroupPage/StorageGroupPage.tsx b/src/containers/StorageGroupPage/StorageGroupPage.tsx index edfc9cb66..d45bacf06 100644 --- a/src/containers/StorageGroupPage/StorageGroupPage.tsx +++ b/src/containers/StorageGroupPage/StorageGroupPage.tsx @@ -19,6 +19,7 @@ import {EFlag} from '../../types/api/enums'; import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; import {useAutoRefreshInterval, useTypedDispatch} from '../../utils/hooks'; +import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery'; import {PaginatedStorage} from '../Storage/PaginatedStorage'; import {storageGroupPageKeyset} from './i18n'; @@ -29,6 +30,7 @@ const storageGroupPageCn = cn('ydb-storage-group-page'); export function StorageGroupPage() { const dispatch = useTypedDispatch(); + const database = useDatabaseFromQuery(); const containerRef = React.useRef(null); const [{groupId}] = useQueryParams({groupId: StringParam}); @@ -42,7 +44,7 @@ export function StorageGroupPage() { const capabilitiesLoaded = useCapabilitiesLoaded(); const groupQuery = storageApi.useGetStorageGroupsInfoQuery( valueIsDefined(groupId) - ? {groupId, shouldUseGroupsHandler, with: 'all', fieldsRequired: 'all'} + ? {groupId, shouldUseGroupsHandler, with: 'all', fieldsRequired: 'all', database} : skipToken, { pollingInterval: autoRefreshInterval, @@ -112,6 +114,7 @@ export function StorageGroupPage() { { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const database = useDatabaseFromQuery(); const { ChangeTime, @@ -48,6 +49,7 @@ export const TabletInfo = ({tablet}: TabletInfoProps) => { tabletInfo.push({ label: tabletInfoKeyset('field_hive'), value: ( + //TODO: add database to getTabletPagePath after fix in backend {HiveId} @@ -59,6 +61,7 @@ export const TabletInfo = ({tablet}: TabletInfoProps) => { tabletInfo.push({ label: tabletInfoKeyset('field_scheme-shard'), value: ( + //TODO: add database to getTabletPagePath after fix in backend {SchemeShard} @@ -80,7 +83,7 @@ export const TabletInfo = ({tablet}: TabletInfoProps) => { { label: tabletInfoKeyset('field_node'), value: ( - + {NodeId} ), @@ -110,19 +113,19 @@ export const TabletInfo = ({tablet}: TabletInfoProps) => { diff --git a/src/containers/Tablet/components/TabletTable/TabletTable.tsx b/src/containers/Tablet/components/TabletTable/TabletTable.tsx index d63b51c7b..db6ebf595 100644 --- a/src/containers/Tablet/components/TabletTable/TabletTable.tsx +++ b/src/containers/Tablet/components/TabletTable/TabletTable.tsx @@ -7,11 +7,12 @@ import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/Re import {TabletState} from '../../../../components/TabletState/TabletState'; import {TabletUptime} from '../../../../components/UptimeViewer/UptimeViewer'; import type {ITabletPreparedHistoryItem} from '../../../../types/store/tablet'; +import {useDatabaseFromQuery} from '../../../../utils/hooks/useDatabaseFromQuery'; import {getDefaultNodePath} from '../../../Node/NodePages'; const TABLET_COLUMNS_WIDTH_LS_KEY = 'tabletTableColumnsWidth'; -const columns: Column[] = [ +const getColumns = (database?: string): Column[] => [ { name: 'Generation', align: DataTable.RIGHT, @@ -43,7 +44,11 @@ const columns: Column[] = [ align: DataTable.RIGHT, sortable: false, render: ({row}) => { - return {row.nodeId}; + return ( + + {row.nodeId} + + ); }, }, { @@ -68,11 +73,12 @@ interface TabletTableProps { } export const TabletTable = ({history}: TabletTableProps) => { + const database = useDatabaseFromQuery(); return ( ; + return ; }, }, { @@ -66,7 +66,9 @@ function getColumns({database}: {database?: string}) { }, render: ({row}) => { const nodePath = - row.NodeId === undefined ? undefined : getDefaultNodePath(row.NodeId); + row.NodeId === undefined + ? undefined + : getDefaultNodePath(row.NodeId, {database}); return {row.NodeId}; }, align: 'right', diff --git a/src/containers/Tenant/Diagnostics/Diagnostics.tsx b/src/containers/Tenant/Diagnostics/Diagnostics.tsx index ead4ae3a4..1c5388d56 100644 --- a/src/containers/Tenant/Diagnostics/Diagnostics.tsx +++ b/src/containers/Tenant/Diagnostics/Diagnostics.tsx @@ -163,6 +163,7 @@ function Diagnostics(props: DiagnosticsProps) { wrapTo={({id}, node) => { const path = getTenantPath({ ...queryParams, + database: tenantName, [TenantTabsGroups.diagnosticsTab]: id, }); diff --git a/src/containers/Tenant/Diagnostics/Network/Network.tsx b/src/containers/Tenant/Diagnostics/Network/Network.tsx index f42934f12..518b9fb8a 100644 --- a/src/containers/Tenant/Diagnostics/Network/Network.tsx +++ b/src/containers/Tenant/Diagnostics/Network/Network.tsx @@ -115,7 +115,9 @@ export function Network({tenantName}: NetworkProps) { Connectivity of node{' '} {clickedNode.NodeId} {' '} diff --git a/src/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx b/src/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx index 0a9f677d9..687a088ca 100644 --- a/src/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx +++ b/src/containers/Tenant/Diagnostics/Partitions/columns/columns.tsx @@ -32,7 +32,7 @@ const b = cn('ydb-diagnostics-partitions-columns'); export const PARTITIONS_COLUMNS_WIDTH_LS_KEY = 'partitionsColumnsWidth'; -export const allColumns: Column[] = [ +export const getAllColumns = (database?: string): Column[] => [ { name: PARTITIONS_COLUMNS_IDS.PARTITION_ID, header: ( @@ -206,7 +206,7 @@ export const allColumns: Column[] = [ row.partitionNodeId && row.partitionHost ? ( @@ -227,7 +227,7 @@ export const allColumns: Column[] = [ row.connectionNodeId && row.connectionHost ? ( @@ -239,8 +239,9 @@ export const allColumns: Column[] = [ // Topics without consumers have partitions data with no data corresponding to consumers // These columns will be empty and should not be displayed -export const generalColumns = allColumns.filter((column) => { - return generalPartitionColumnsIds.includes( - column.name as (typeof generalPartitionColumnsIds)[number], - ); -}); +export const getGeneralColumns = (database?: string) => + getAllColumns(database).filter((column) => { + return generalPartitionColumnsIds.includes( + column.name as (typeof generalPartitionColumnsIds)[number], + ); + }); diff --git a/src/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts b/src/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts index 5b83a4781..b58f4b45c 100644 --- a/src/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts +++ b/src/containers/Tenant/Diagnostics/Partitions/utils/useGetPartitionsColumns.ts @@ -2,27 +2,29 @@ import React from 'react'; import type {Column} from '@gravity-ui/react-data-table'; -import {allColumns, generalColumns} from '../columns'; +import {useDatabaseFromQuery} from '../../../../../utils/hooks/useDatabaseFromQuery'; +import {getAllColumns, getGeneralColumns} from '../columns'; import {allPartitionsColumnsIds, generalPartitionColumnsIds} from './constants'; import type {PreparedPartitionDataWithHosts} from './types'; // Columns are different for partitions with consumers and without export const useGetPartitionsColumns = ( - selectedConsumer: string | undefined, + selectedConsumer?: string, ): [Column[], string[]] => { + const database = useDatabaseFromQuery(); const [columns, setColumns] = React.useState[]>([]); const [columnsIdsForSelector, setColumnsIdsForSelector] = React.useState([]); React.useEffect(() => { if (selectedConsumer) { - setColumns(allColumns); + setColumns(getAllColumns(database)); setColumnsIdsForSelector(allPartitionsColumnsIds); } else { - setColumns(generalColumns); + setColumns(getGeneralColumns(database)); setColumnsIdsForSelector(generalPartitionColumnsIds); } - }, [selectedConsumer]); + }, [selectedConsumer, database]); return [columns, columnsIdsForSelector]; }; diff --git a/src/containers/Tenant/Diagnostics/TopShards/TopShards.tsx b/src/containers/Tenant/Diagnostics/TopShards/TopShards.tsx index 5b44dc462..389da466f 100644 --- a/src/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +++ b/src/containers/Tenant/Diagnostics/TopShards/TopShards.tsx @@ -127,7 +127,11 @@ export const TopShards = ({tenantName, path, type}: TopShardsProps) => { }; const tableColumns = React.useMemo(() => { - const rawColumns: Column[] = getShardsWorkloadColumns(tenantName, location); + const rawColumns: Column[] = getShardsWorkloadColumns( + tenantName, + location, + tenantName, + ); const columns: Column[] = rawColumns.map((column) => ({ ...column, diff --git a/src/containers/Tenant/Diagnostics/TopShards/columns/columns.tsx b/src/containers/Tenant/Diagnostics/TopShards/columns/columns.tsx index 614f31b53..b76dd85f5 100644 --- a/src/containers/Tenant/Diagnostics/TopShards/columns/columns.tsx +++ b/src/containers/Tenant/Diagnostics/TopShards/columns/columns.tsx @@ -63,17 +63,21 @@ const tabletIdColumn: Column = { width: 220, }; -const nodeIdColumn: Column = { +const getNodeIdColumn = (database?: string): Column => ({ name: TOP_SHARDS_COLUMNS_IDS.NodeId, header: TOP_SHARDS_COLUMNS_TITLES.NodeId, render: ({row}) => { if (!row.NodeId) { return '–'; } - return {row.NodeId}; + return ( + + {row.NodeId} + + ); }, align: DataTable.RIGHT, -}; +}); const topShardsCpuCoresColumn: Column = { name: TOP_SHARDS_COLUMNS_IDS.CPUCores, @@ -99,13 +103,17 @@ const inFlightTxCountColumn: Column = { align: DataTable.RIGHT, }; -export const getShardsWorkloadColumns = (schemaPath: string, location: Location) => { +export const getShardsWorkloadColumns = ( + schemaPath: string, + location: Location, + database?: string, +) => { return [ getPathColumn(schemaPath, location), cpuCoresColumn, dataSizeColumn, tabletIdColumn, - nodeIdColumn, + getNodeIdColumn(database), inFlightTxCountColumn, ]; }; diff --git a/src/containers/VDiskPage/VDiskPage.tsx b/src/containers/VDiskPage/VDiskPage.tsx index 922e11be0..5c9c241b3 100644 --- a/src/containers/VDiskPage/VDiskPage.tsx +++ b/src/containers/VDiskPage/VDiskPage.tsx @@ -37,10 +37,11 @@ export function VDiskPage() { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); const newDiskApiAvailable = useDiskPagesAvailable(); - const [{nodeId, pDiskId, vDiskSlotId}] = useQueryParams({ + const [{nodeId, pDiskId, vDiskSlotId, database}] = useQueryParams({ nodeId: StringParam, pDiskId: StringParam, vDiskSlotId: StringParam, + database: StringParam, }); React.useEffect(() => { @@ -50,7 +51,7 @@ export function VDiskPage() { const [autoRefreshInterval] = useAutoRefreshInterval(); const params = valueIsDefined(nodeId) && valueIsDefined(pDiskId) && valueIsDefined(vDiskSlotId) - ? {nodeId, pDiskId, vDiskSlotId} + ? {nodeId, pDiskId, vDiskSlotId, database: database?.toString()} : skipToken; const { currentData: vDiskData = {}, @@ -186,6 +187,8 @@ export function VDiskPage() {
{vDiskPageKeyset('storage')}
( @@ -65,6 +69,7 @@ export class PDiskAPI extends BaseYdbAPI { { node_id: nodeId, pdisk_id: pDiskId, + database, }, {concurrentId, requestConfig: {signal}}, ); diff --git a/src/services/api/viewer.ts b/src/services/api/viewer.ts index 6c6342fbc..775b83513 100644 --- a/src/services/api/viewer.ts +++ b/src/services/api/viewer.ts @@ -53,11 +53,16 @@ export class ViewerAPI extends BaseYdbAPI { ); } - getNodeInfo(id?: string | number, {concurrentId, signal}: AxiosOptions = {}) { + getNodeInfo( + id?: string | number, + database?: string, + {concurrentId, signal}: AxiosOptions = {}, + ) { return this.get( this.getPath('/viewer/json/sysinfo?enums=true'), { node_id: id, + database, }, {concurrentId, requestConfig: {signal}}, ); @@ -449,10 +454,12 @@ export class ViewerAPI extends BaseYdbAPI { vDiskSlotId, pDiskId, nodeId, + database, }: { vDiskSlotId: string | number; pDiskId: string | number; nodeId: string | number; + database?: string; }, {concurrentId, signal}: AxiosOptions = {}, ) { @@ -461,19 +468,25 @@ export class ViewerAPI extends BaseYdbAPI { { node_id: nodeId, filter: `(PDiskId=${pDiskId};VDiskSlotId=${vDiskSlotId})`, + database, }, {concurrentId, requestConfig: {signal}}, ); } getNodeWhiteboardPDiskInfo( - {nodeId, pDiskId}: {nodeId: string | number; pDiskId: string | number}, + { + nodeId, + pDiskId, + database, + }: {nodeId: string | number; pDiskId: string | number; database?: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get( this.getPath('/viewer/json/pdiskinfo?enums=true'), { filter: `(NodeId=${nodeId}${pDiskId ? `;PDiskId=${pDiskId}` : ''})`, + database, }, {concurrentId, requestConfig: {signal}}, ); diff --git a/src/store/reducers/capabilities/capabilities.ts b/src/store/reducers/capabilities/capabilities.ts index 5ff82b977..d08a004ab 100644 --- a/src/store/reducers/capabilities/capabilities.ts +++ b/src/store/reducers/capabilities/capabilities.ts @@ -50,5 +50,5 @@ export async function queryCapability( const thunk = capabilitiesApi.util.getRunningQueryThunk('getClusterCapabilities', {database}); await dispatch(thunk); - return selectCapabilityVersion(getState(), capability) || 0; + return selectCapabilityVersion(getState(), capability, database) || 0; } diff --git a/src/store/reducers/node/node.ts b/src/store/reducers/node/node.ts index 0ba5a55c2..215cc21fe 100644 --- a/src/store/reducers/node/node.ts +++ b/src/store/reducers/node/node.ts @@ -5,9 +5,9 @@ import {prepareNodeData} from './utils'; export const nodeApi = api.injectEndpoints({ endpoints: (build) => ({ getNodeInfo: build.query({ - queryFn: async ({nodeId}: {nodeId: string}, {signal}) => { + queryFn: async ({nodeId, database}: {nodeId: string; database?: string}, {signal}) => { try { - const data = await window.api.viewer.getNodeInfo(nodeId, {signal}); + const data = await window.api.viewer.getNodeInfo(nodeId, database, {signal}); return {data: prepareNodeData(data)}; } catch (error) { return {error}; diff --git a/src/store/reducers/pdisk/pdisk.ts b/src/store/reducers/pdisk/pdisk.ts index 47bb253e3..1a5ba4486 100644 --- a/src/store/reducers/pdisk/pdisk.ts +++ b/src/store/reducers/pdisk/pdisk.ts @@ -9,13 +9,17 @@ import {preparePDiskDataResponse} from './utils'; interface PDiskParams { nodeId: number | string; pDiskId: number | string; + database?: string; } export const pDiskApi = api.injectEndpoints({ endpoints: (build) => ({ getPdiskInfo: build.query({ - queryFn: async ({nodeId, pDiskId}: PDiskParams, {signal, getState, dispatch}) => { - const pDiskInfoHandlerVersion = await queryCapability('/pdisk/info', undefined, { + queryFn: async ( + {nodeId, pDiskId, database}: PDiskParams, + {signal, getState, dispatch}, + ) => { + const pDiskInfoHandlerVersion = await queryCapability('/pdisk/info', database, { getState: getState as GetState, dispatch, }); @@ -23,10 +27,13 @@ export const pDiskApi = api.injectEndpoints({ let diskInfoPromise: Promise; if (newApiAvailable) { - diskInfoPromise = window.api.pdisk.getPDiskInfo({nodeId, pDiskId}, {signal}); + diskInfoPromise = window.api.pdisk.getPDiskInfo( + {nodeId, pDiskId, database}, + {signal}, + ); } else { diskInfoPromise = window.api.viewer - .getNodeWhiteboardPDiskInfo({nodeId, pDiskId}, {signal}) + .getNodeWhiteboardPDiskInfo({nodeId, pDiskId, database}, {signal}) .then((result) => { if (result.PDiskStateInfo) { return { @@ -45,7 +52,7 @@ export const pDiskApi = api.injectEndpoints({ try { const response = await Promise.all([ diskInfoPromise, - window.api.viewer.getNodeInfo(nodeId, {signal}), + window.api.viewer.getNodeInfo(nodeId, database, {signal}), ]); const data = preparePDiskDataResponse(response); return {data}; diff --git a/src/store/reducers/vdisk/vdisk.ts b/src/store/reducers/vdisk/vdisk.ts index 4f5964a8c..420be76aa 100644 --- a/src/store/reducers/vdisk/vdisk.ts +++ b/src/store/reducers/vdisk/vdisk.ts @@ -7,17 +7,27 @@ interface VDiskDataRequestParams { nodeId: number | string; pDiskId: number | string; vDiskSlotId: number | string; + database?: string; } export const vDiskApi = api.injectEndpoints({ endpoints: (build) => ({ getVDiskData: build.query({ - queryFn: async ({nodeId, pDiskId, vDiskSlotId}: VDiskDataRequestParams, {signal}) => { + queryFn: async ( + {nodeId, pDiskId, vDiskSlotId, database}: VDiskDataRequestParams, + {signal}, + ) => { try { const response = await Promise.all([ - window.api.viewer.getVDiskInfo({nodeId, pDiskId, vDiskSlotId}, {signal}), - window.api.viewer.getNodeWhiteboardPDiskInfo({nodeId, pDiskId}, {signal}), - window.api.viewer.getNodeInfo(nodeId, {signal}), + window.api.viewer.getVDiskInfo( + {nodeId, pDiskId, vDiskSlotId, database}, + {signal}, + ), + window.api.viewer.getNodeWhiteboardPDiskInfo( + {nodeId, pDiskId, database}, + {signal}, + ), + window.api.viewer.getNodeInfo(nodeId, database, {signal}), ]); const data = prepareVDiskDataResponse(response); return {data}; diff --git a/src/utils/developerUI/__test__/developerUI.test.ts b/src/utils/developerUI/__test__/developerUI.test.ts index 09473baff..2731c5d40 100644 --- a/src/utils/developerUI/__test__/developerUI.test.ts +++ b/src/utils/developerUI/__test__/developerUI.test.ts @@ -49,13 +49,14 @@ describe('Developer UI links generators', () => { ), ).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1'); }); - it('should create full link with host with existing node path with nodeId', () => { + it('should create full link with host with existing node path with nodeId and database', () => { expect( createDeveloperUILinkWithNodeId( 1, 'http://ydb-vla-dev02-001.search.yandex.net:8765/node/3', + 'my_database', ), - ).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1'); + ).toBe('http://ydb-vla-dev02-001.search.yandex.net:8765/node/1?database=my_database'); }); }); describe('createPDiskDeveloperUILink', () => { diff --git a/src/utils/developerUI/developerUI.ts b/src/utils/developerUI/developerUI.ts index 62607a000..80c32d7b9 100644 --- a/src/utils/developerUI/developerUI.ts +++ b/src/utils/developerUI/developerUI.ts @@ -1,16 +1,25 @@ import {backend} from '../../store'; import {pad9} from '../utils'; -export function createDeveloperUIInternalPageHref(host = backend) { - return host + '/internal'; +export function createDeveloperUIInternalPageHref(host = backend, database?: string) { + const queryParams = getDatabaseQueryString(database); + return host + '/internal' + queryParams; } export function createDeveloperUIMonitoringPageHref(host = backend) { return host + '/monitoring'; } -// Current node connects with target node by itself using nodeId -export const createDeveloperUILinkWithNodeId = (nodeId: number | string, host = backend) => { +function getDatabaseQueryString(database?: string) { + const params = new URLSearchParams(); + if (database) { + params.set('database', database); + } + const paramsString = params.toString(); + return paramsString ? '?' + paramsString : ''; +} + +export function createBaseDeveloperUILinkWithNodeId(nodeId: number | string, host = backend) { const nodePathRegexp = /\/node\/\d+\/?$/g; // In case current backend is already relative node path ({host}/node/{nodeId}) @@ -20,18 +29,39 @@ export const createDeveloperUILinkWithNodeId = (nodeId: number | string, host = } return `${host ?? ''}/node/${nodeId}`; +} + +// Current node connects with target node by itself using nodeId +export const createDeveloperUILinkWithNodeId = ( + nodeId: number | string, + host = backend, + database?: string, +) => { + const href = createBaseDeveloperUILinkWithNodeId(nodeId, host); + + const queryParams = getDatabaseQueryString(database); + + return `${href}${queryParams}`; }; interface PDiskDeveloperUILinkParams { nodeId: number | string; pDiskId: number | string; host?: string; + database?: string; } -export const createPDiskDeveloperUILink = ({nodeId, pDiskId, host}: PDiskDeveloperUILinkParams) => { - const pdiskPath = '/actors/pdisks/pdisk' + pad9(pDiskId); +export const createPDiskDeveloperUILink = ({ + nodeId, + pDiskId, + host, + database, +}: PDiskDeveloperUILinkParams) => { + const queryParams = getDatabaseQueryString(database); + + const pdiskPath = '/actors/pdisks/pdisk' + pad9(pDiskId) + queryParams; - return createDeveloperUILinkWithNodeId(nodeId, host) + pdiskPath; + return createBaseDeveloperUILinkWithNodeId(nodeId, host) + pdiskPath; }; interface VDiskDeveloperUILinkParams extends PDiskDeveloperUILinkParams { @@ -43,18 +73,28 @@ export const createVDiskDeveloperUILink = ({ pDiskId, vDiskSlotId, host, + database, }: VDiskDeveloperUILinkParams) => { - const vdiskPath = '/actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(vDiskSlotId); + const queryParams = getDatabaseQueryString(database); - return createDeveloperUILinkWithNodeId(nodeId, host) + vdiskPath; + const vdiskPath = + '/actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(vDiskSlotId) + queryParams; + + return createBaseDeveloperUILinkWithNodeId(nodeId, host) + vdiskPath; }; export function createTabletDeveloperUIHref( tabletId: number | string, + database?: string, tabletPage?: string, searchParam = 'TabletID', host = backend, ) { const subPage = tabletPage ? `/${tabletPage}` : ''; - return `${host}/tablets${subPage}?${searchParam}=${tabletId}`; + const params = new URLSearchParams(); + params.set(searchParam, String(tabletId)); + if (database) { + params.set('database', database); + } + return `${host}/tablets${subPage}?${params.toString()}`; } diff --git a/src/utils/hooks/useNodeDeveloperUIHref.ts b/src/utils/hooks/useNodeDeveloperUIHref.ts index 868e1fce7..81a6c812e 100644 --- a/src/utils/hooks/useNodeDeveloperUIHref.ts +++ b/src/utils/hooks/useNodeDeveloperUIHref.ts @@ -6,10 +6,12 @@ import { createDeveloperUILinkWithNodeId, } from '../developerUI/developerUI'; +import {useDatabaseFromQuery} from './useDatabaseFromQuery'; import {useIsUserAllowedToMakeChanges} from './useIsUserAllowedToMakeChanges'; export function useNodeDeveloperUIHref(node?: PreparedNode) { const {balancer} = useClusterBaseInfo(); + const database = useDatabaseFromQuery(); const {additionalNodesProps} = useAdditionalNodeProps({balancer}); const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); @@ -23,7 +25,7 @@ export function useNodeDeveloperUIHref(node?: PreparedNode) { } if (node?.NodeId) { - const developerUIHref = createDeveloperUILinkWithNodeId(node.NodeId); + const developerUIHref = createDeveloperUILinkWithNodeId(node.NodeId, undefined, database); return createDeveloperUIInternalPageHref(developerUIHref); }