From 68ab1dac9927276b14595be042fc96ca2097f205 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Tue, 5 Aug 2025 12:36:02 +0300 Subject: [PATCH 1/3] feat: restrictions for users without IsViewerAllowed role --- src/components/VDiskPopup/VDiskPopup.tsx | 8 +++++-- src/components/nodesColumns/constants.ts | 6 ++++++ src/containers/Nodes/Nodes.tsx | 21 +++++++++++++++---- .../Nodes/NodesControls/NodesControls.tsx | 4 +++- .../Nodes/useNodesPageQueryParams.ts | 7 ++++++- .../columns/constants.ts | 6 ++++++ .../columns/hooks.ts | 17 ++++++++++++--- .../Tenant/Diagnostics/Diagnostics.tsx | 3 +++ .../Tenant/Diagnostics/DiagnosticsPages.ts | 10 ++++++--- src/store/reducers/cluster/cluster.ts | 6 +++++- 10 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/components/VDiskPopup/VDiskPopup.tsx b/src/components/VDiskPopup/VDiskPopup.tsx index ace30002ec..e57953472b 100644 --- a/src/components/VDiskPopup/VDiskPopup.tsx +++ b/src/components/VDiskPopup/VDiskPopup.tsx @@ -13,7 +13,10 @@ 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 {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; +import { + useIsUserAllowedToMakeChanges, + useIsViewerUser, +} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {bytesToGB, bytesToSpeed} from '../../utils/utils'; import type {InfoViewerItem} from '../InfoViewer'; import {InfoViewer} from '../InfoViewer'; @@ -221,6 +224,7 @@ interface VDiskPopupProps { export const VDiskPopup = ({data}: VDiskPopupProps) => { const isFullData = isFullVDiskData(data); + const isViewerUser = useIsViewerUser(); const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); @@ -257,7 +261,7 @@ export const VDiskPopup = ({data}: VDiskPopupProps) => {
{data.DonorMode && } - {pdiskInfo && } + {pdiskInfo && isViewerUser && } {donorsInfo.length > 0 && }
); diff --git a/src/components/nodesColumns/constants.ts b/src/components/nodesColumns/constants.ts index 86e67f30e0..7416714baa 100644 --- a/src/components/nodesColumns/constants.ts +++ b/src/components/nodesColumns/constants.ts @@ -43,6 +43,12 @@ export function isMonitoringUserNodesColumn(columnId: string): boolean { return MONITORING_USER_COLUMNS_IDS.includes(columnId as NodesColumnId); } +// Columns, that should displayed only for users with isViewerAllowed:true +const VIEWER_USER_COLUMNS_IDS: NodesColumnId[] = ['LoadAverage']; +export function isViewerUserNodesColumn(columnId: string): boolean { + return VIEWER_USER_COLUMNS_IDS.some((el) => el === columnId); +} + // This code is running when module is initialized and correct language may not be set yet // get functions guarantee that i18n fields will be inited on render with current render language export const NODES_COLUMNS_TITLES = { diff --git a/src/containers/Nodes/Nodes.tsx b/src/containers/Nodes/Nodes.tsx index 6b0fb97776..8751e76378 100644 --- a/src/containers/Nodes/Nodes.tsx +++ b/src/containers/Nodes/Nodes.tsx @@ -1,12 +1,18 @@ import React from 'react'; import type {Column} from '../../components/PaginatedTable'; -import {isMonitoringUserNodesColumn} from '../../components/nodesColumns/constants'; +import { + isMonitoringUserNodesColumn, + isViewerUserNodesColumn, +} from '../../components/nodesColumns/constants'; import type {NodesColumnId} from '../../components/nodesColumns/constants'; import type {NodesPreparedEntity} from '../../store/reducers/nodes/types'; import type {AdditionalNodesProps} from '../../types/additionalProps'; import type {NodesGroupByField} from '../../types/api/nodes'; -import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; +import { + useIsUserAllowedToMakeChanges, + useIsViewerUser, +} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import {PaginatedNodes} from './PaginatedNodes'; import {getNodesColumns} from './columns/columns'; @@ -45,13 +51,20 @@ export function Nodes({ groupByParams = ALL_NODES_GROUP_BY_PARAMS, }: NodesProps) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const isViewerUser = useIsViewerUser(); const preparedColumns = React.useMemo(() => { if (isUserAllowedToMakeChanges) { return columns; } - return columns.filter((column) => !isMonitoringUserNodesColumn(column.name)); - }, [columns, isUserAllowedToMakeChanges]); + const filteredColumns = columns.filter( + (column) => !isMonitoringUserNodesColumn(column.name), + ); + if (isViewerUser) { + return filteredColumns; + } + return filteredColumns.filter((column) => !isViewerUserNodesColumn(column.name)); + }, [columns, isUserAllowedToMakeChanges, isViewerUser]); return ( { handleGroupByParamChange(value[0]); diff --git a/src/containers/Nodes/useNodesPageQueryParams.ts b/src/containers/Nodes/useNodesPageQueryParams.ts index b06f903998..158810b4ff 100644 --- a/src/containers/Nodes/useNodesPageQueryParams.ts +++ b/src/containers/Nodes/useNodesPageQueryParams.ts @@ -2,6 +2,7 @@ import {StringParam, useQueryParams} from 'use-query-params'; import {useViewerNodesHandlerHasGroupingBySystemState} from '../../store/reducers/capabilities/hooks'; import type {NodesGroupByField, NodesPeerRole} from '../../types/api/nodes'; +import {useIsViewerUser} from '../../utils/hooks/useIsUserAllowedToMakeChanges'; import type {NodesUptimeFilterValues} from '../../utils/nodes'; import {nodesUptimeFilterValuesSchema} from '../../utils/nodes'; @@ -16,9 +17,13 @@ export function useNodesPageQueryParams(groupByParams: NodesGroupByField[] | und nodesGroupBy: StringParam, }); + const isViewerUser = useIsViewerUser(); + const uptimeFilter = nodesUptimeFilterValuesSchema.parse(queryParams.uptimeFilter); const searchValue = queryParams.search ?? ''; - const peerRoleFilter = parseNodesPeerRoleFilter(queryParams.peerRole); + const peerRoleFilter = isViewerUser + ? parseNodesPeerRoleFilter(queryParams.peerRole) + : 'database'; const systemStateGroupingAvailable = useViewerNodesHandlerHasGroupingBySystemState(); const groupByParam = parseNodesGroupByParam( diff --git a/src/containers/Storage/PaginatedStorageGroupsTable/columns/constants.ts b/src/containers/Storage/PaginatedStorageGroupsTable/columns/constants.ts index ac9a7c3546..8125fee8d4 100644 --- a/src/containers/Storage/PaginatedStorageGroupsTable/columns/constants.ts +++ b/src/containers/Storage/PaginatedStorageGroupsTable/columns/constants.ts @@ -55,6 +55,12 @@ export const DEFAULT_STORAGE_GROUPS_COLUMNS: StorageGroupsColumnId[] = [ 'VDisks', ]; +// Columns, that should displayed only for users with isViewerAllowed:true +const VIEWER_USER_COLUMNS_IDS: StorageGroupsColumnId[] = ['DiskSpace']; +export function isViewerGroupsColumn(columnId: string): boolean { + return VIEWER_USER_COLUMNS_IDS.some((el) => el === columnId); +} + export const REQUIRED_STORAGE_GROUPS_COLUMNS: StorageGroupsColumnId[] = ['GroupId']; // This code is running when module is initialized and correct language may not be set yet diff --git a/src/containers/Storage/PaginatedStorageGroupsTable/columns/hooks.ts b/src/containers/Storage/PaginatedStorageGroupsTable/columns/hooks.ts index bcb422ba30..cbc95dce41 100644 --- a/src/containers/Storage/PaginatedStorageGroupsTable/columns/hooks.ts +++ b/src/containers/Storage/PaginatedStorageGroupsTable/columns/hooks.ts @@ -1,7 +1,10 @@ import React from 'react'; import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants'; -import {useIsUserAllowedToMakeChanges} from '../../../../utils/hooks/useIsUserAllowedToMakeChanges'; +import { + useIsUserAllowedToMakeChanges, + useIsViewerUser, +} from '../../../../utils/hooks/useIsUserAllowedToMakeChanges'; import {useSelectedColumns} from '../../../../utils/hooks/useSelectedColumns'; import {getStorageGroupsColumns} from './columns'; @@ -12,6 +15,7 @@ import { STORAGE_GROUPS_COLUMNS_TITLES, STORAGE_GROUPS_SELECTED_COLUMNS_LS_KEY, isMonitoringUserGroupsColumn, + isViewerGroupsColumn, } from './constants'; import type {GetStorageGroupsColumnsParams} from './types'; @@ -20,6 +24,7 @@ export function useStorageGroupsSelectedColumns({ viewContext, }: GetStorageGroupsColumnsParams) { const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges(); + const isViewerUser = useIsViewerUser(); const columns = React.useMemo(() => { const allColumns = getStorageGroupsColumns({viewContext}); @@ -27,8 +32,14 @@ export function useStorageGroupsSelectedColumns({ if (isUserAllowedToMakeChanges) { return allColumns; } - return allColumns.filter((column) => !isMonitoringUserGroupsColumn(column.name)); - }, [isUserAllowedToMakeChanges, viewContext]); + const filteredColumns = allColumns.filter( + (column) => !isMonitoringUserGroupsColumn(column.name), + ); + if (isViewerUser) { + return filteredColumns; + } + return filteredColumns.filter((column) => !isViewerGroupsColumn(column.name)); + }, [isUserAllowedToMakeChanges, viewContext, isViewerUser]); const requiredColumns = React.useMemo(() => { if (visibleEntities === VISIBLE_ENTITIES.missing) { diff --git a/src/containers/Tenant/Diagnostics/Diagnostics.tsx b/src/containers/Tenant/Diagnostics/Diagnostics.tsx index 55a25031fa..e1d4c66919 100644 --- a/src/containers/Tenant/Diagnostics/Diagnostics.tsx +++ b/src/containers/Tenant/Diagnostics/Diagnostics.tsx @@ -17,6 +17,7 @@ import type {AdditionalNodesProps, AdditionalTenantsProps} from '../../../types/ import {uiFactory} from '../../../uiFactory/uiFactory'; import {cn} from '../../../utils/cn'; import {useScrollPosition, useTypedDispatch, useTypedSelector} from '../../../utils/hooks'; +import {useIsViewerUser} from '../../../utils/hooks/useIsUserAllowedToMakeChanges'; import {Heatmap} from '../../Heatmap'; import {Nodes} from '../../Nodes/Nodes'; import {Operations} from '../../Operations'; @@ -63,11 +64,13 @@ function Diagnostics(props: DiagnosticsProps) { const hasFeatureFlags = useFeatureFlagsAvailable(); const hasTopicData = useTopicDataAvailable(); + const isViewerUser = useIsViewerUser(); const pages = getPagesByType(type, subType, { hasFeatureFlags, hasTopicData, isTopLevel: path === database, hasBackups: typeof uiFactory.renderBackups === 'function' && Boolean(controlPlane), + hasConfigs: isViewerUser, }); let activeTab = pages.find((el) => el.id === diagnosticsTab); if (!activeTab) { diff --git a/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts b/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts index 673c0c2321..6ffef9c123 100644 --- a/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts +++ b/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts @@ -176,6 +176,7 @@ export const getPagesByType = ( hasTopicData?: boolean; isTopLevel?: boolean; hasBackups?: boolean; + hasConfigs?: boolean; }, ) => { const subTypePages = subType ? pathSubTypeToPages[subType] : undefined; @@ -183,16 +184,19 @@ export const getPagesByType = ( let pages = subTypePages || typePages || DIR_PAGES; if (isTopicEntityType(type) && !options?.hasTopicData) { - return pages?.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.topicData); + pages = pages?.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.topicData); } if (isDatabaseEntityType(type) || options?.isTopLevel) { pages = DATABASE_PAGES; if (!options?.hasFeatureFlags) { - return pages.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.configs); + pages = pages.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.configs); } } if (!options?.hasBackups) { - return pages.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.backups); + pages = pages.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.backups); + } + if (!options?.hasConfigs) { + pages = pages.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.configs); } return pages; }; diff --git a/src/store/reducers/cluster/cluster.ts b/src/store/reducers/cluster/cluster.ts index 403e883cbb..0484e84f33 100644 --- a/src/store/reducers/cluster/cluster.ts +++ b/src/store/reducers/cluster/cluster.ts @@ -10,6 +10,7 @@ import type {TClusterInfo} from '../../../types/api/cluster'; import type {TTabletStateInfo} from '../../../types/api/tablet'; import {CLUSTER_DEFAULT_TITLE, DEFAULT_CLUSTER_TAB_KEY} from '../../../utils/constants'; import {useClusterNameFromQuery} from '../../../utils/hooks/useDatabaseFromQuery'; +import {useIsViewerUser} from '../../../utils/hooks/useIsUserAllowedToMakeChanges'; import {isQueryErrorResponse} from '../../../utils/query'; import type {RootState} from '../../defaultStore'; import {api} from '../api'; @@ -139,8 +140,11 @@ export const clusterApi = api.injectEndpoints({ export function useClusterBaseInfo() { const clusterNameFromQuery = useClusterNameFromQuery(); + const isViewerUser = useIsViewerUser(); - const {currentData} = clusterApi.useGetClusterBaseInfoQuery(clusterNameFromQuery ?? skipToken); + const {currentData} = clusterApi.useGetClusterBaseInfoQuery(clusterNameFromQuery ?? skipToken, { + skip: !isViewerUser, + }); const {solomon: monitoring, name, title, trace_view: traceView, ...data} = currentData || {}; From ec547d7d72af0011589d5042d41ea320ec259756 Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Tue, 5 Aug 2025 13:07:33 +0300 Subject: [PATCH 2/3] fix: review --- src/components/VDiskPopup/VDiskPopup.tsx | 58 ++++++++++++++---------- src/components/VDiskPopup/i18n/en.json | 21 +++++++++ src/components/VDiskPopup/i18n/index.ts | 7 +++ 3 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 src/components/VDiskPopup/i18n/en.json create mode 100644 src/components/VDiskPopup/i18n/index.ts diff --git a/src/components/VDiskPopup/VDiskPopup.tsx b/src/components/VDiskPopup/VDiskPopup.tsx index e57953472b..1af84d0048 100644 --- a/src/components/VDiskPopup/VDiskPopup.tsx +++ b/src/components/VDiskPopup/VDiskPopup.tsx @@ -26,6 +26,8 @@ import {preparePDiskData} from '../PDiskPopup/PDiskPopup'; import {getVDiskLink} from '../VDisk/utils'; import {vDiskInfoKeyset} from '../VDiskInfo/i18n'; +import {vDiskPopupKeyset} from './i18n'; + import './VDiskPopup.scss'; const b = cn('vdisk-storage-popup'); @@ -33,16 +35,18 @@ const b = cn('vdisk-storage-popup'); const prepareUnavailableVDiskData = (data: UnavailableDonor, withDeveloperUILink?: boolean) => { const {NodeId, PDiskId, VSlotId, StoragePoolName} = data; - const vdiskData: InfoViewerItem[] = [{label: 'State', value: 'not available'}]; + const vdiskData: InfoViewerItem[] = [ + {label: vDiskPopupKeyset('label_state'), value: vDiskPopupKeyset('context_not-available')}, + ]; if (StoragePoolName) { - vdiskData.push({label: 'StoragePool', value: StoragePoolName}); + vdiskData.push({label: vDiskPopupKeyset('label_storage-pool'), value: StoragePoolName}); } vdiskData.push( - {label: 'NodeId', value: NodeId ?? EMPTY_DATA_PLACEHOLDER}, - {label: 'PDiskId', value: PDiskId ?? EMPTY_DATA_PLACEHOLDER}, - {label: 'VSlotId', value: VSlotId ?? EMPTY_DATA_PLACEHOLDER}, + {label: vDiskPopupKeyset('label_node-id'), value: NodeId ?? EMPTY_DATA_PLACEHOLDER}, + {label: vDiskPopupKeyset('label_pdisk-id'), value: PDiskId ?? EMPTY_DATA_PLACEHOLDER}, + {label: vDiskPopupKeyset('label_vslot-id'), value: VSlotId ?? EMPTY_DATA_PLACEHOLDER}, ); if ( @@ -58,7 +62,7 @@ const prepareUnavailableVDiskData = (data: UnavailableDonor, withDeveloperUILink }); vdiskData.push({ - label: 'Links', + label: vDiskPopupKeyset('label_links'), value: , }); } @@ -88,58 +92,61 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => } = data; const vdiskData: InfoViewerItem[] = [ - {label: 'VDisk', value: StringifiedId}, - {label: 'State', value: VDiskState ?? 'not available'}, + {label: vDiskPopupKeyset('label_vdisk'), value: StringifiedId}, + { + label: vDiskPopupKeyset('label_state'), + value: VDiskState ?? vDiskPopupKeyset('context_not-available'), + }, ]; if (StoragePoolName) { - vdiskData.push({label: 'StoragePool', value: StoragePoolName}); + vdiskData.push({label: vDiskPopupKeyset('label_storage-pool'), value: StoragePoolName}); } if (SatisfactionRank && SatisfactionRank.FreshRank?.Flag !== EFlag.Green) { vdiskData.push({ - label: 'Fresh', + label: vDiskPopupKeyset('label_fresh'), value: SatisfactionRank.FreshRank?.Flag, }); } if (SatisfactionRank && SatisfactionRank.LevelRank?.Flag !== EFlag.Green) { vdiskData.push({ - label: 'Level', + label: vDiskPopupKeyset('label_level'), value: SatisfactionRank.LevelRank?.Flag, }); } if (SatisfactionRank && SatisfactionRank.FreshRank?.RankPercent) { vdiskData.push({ - label: 'Fresh', + label: vDiskPopupKeyset('label_fresh'), value: SatisfactionRank.FreshRank.RankPercent, }); } if (SatisfactionRank && SatisfactionRank.LevelRank?.RankPercent) { vdiskData.push({ - label: 'Level', + label: vDiskPopupKeyset('label_level'), value: SatisfactionRank.LevelRank.RankPercent, }); } if (DiskSpace && DiskSpace !== EFlag.Green) { - vdiskData.push({label: 'Space', value: DiskSpace}); + vdiskData.push({label: vDiskPopupKeyset('label_space'), value: DiskSpace}); } if (FrontQueues && FrontQueues !== EFlag.Green) { - vdiskData.push({label: 'FrontQueues', value: FrontQueues}); + vdiskData.push({label: vDiskPopupKeyset('label_front-queues'), value: FrontQueues}); } if (Replicated === false && VDiskState === EVDiskState.OK) { - vdiskData.push({label: 'Replicated', value: 'NO'}); + vdiskData.push({label: vDiskPopupKeyset('label_replicated'), value: 'NO'}); // Only show replication progress and time remaining when disk is not replicated and state is OK if (valueIsDefined(ReplicationProgress)) { const progressPercent = Math.round(ReplicationProgress * 100); vdiskData.push({ - label: 'Progress', + label: vDiskPopupKeyset('label_progress'), value: `${progressPercent}%`, }); } @@ -148,7 +155,7 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => const timeRemaining = formatUptimeInSeconds(ReplicationSecondsRemaining); if (timeRemaining) { vdiskData.push({ - label: 'Remaining', + label: vDiskPopupKeyset('label_remaining'), value: timeRemaining, }); } @@ -156,23 +163,26 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => } if (UnsyncedVDisks) { - vdiskData.push({label: 'UnsyncVDisks', value: UnsyncedVDisks}); + vdiskData.push({label: vDiskPopupKeyset('label_unsync-vdisks'), value: UnsyncedVDisks}); } if (Number(AllocatedSize)) { vdiskData.push({ - label: 'Allocated', + label: vDiskPopupKeyset('label_allocated'), value: bytesToGB(AllocatedSize), }); } if (Number(ReadThroughput)) { - vdiskData.push({label: 'Read', value: bytesToSpeed(ReadThroughput)}); + vdiskData.push({ + label: vDiskPopupKeyset('label_read'), + value: bytesToSpeed(ReadThroughput), + }); } if (Number(WriteThroughput)) { vdiskData.push({ - label: 'Write', + label: vDiskPopupKeyset('label_write'), value: bytesToSpeed(WriteThroughput), }); } @@ -194,7 +204,7 @@ const prepareVDiskData = (data: PreparedVDisk, withDeveloperUILink?: boolean) => const vDiskPagePath = getVDiskLink({VDiskSlotId, PDiskId, NodeId, StringifiedId}); if (vDiskPagePath) { vdiskData.push({ - label: 'Links', + label: vDiskPopupKeyset('label_links'), value: ( { const donors = data.Donors; for (const donor of donors) { donorsInfo.push({ - label: 'VDisk', + label: vDiskPopupKeyset('label_vdisk'), value: {donor.StringifiedId}, }); } diff --git a/src/components/VDiskPopup/i18n/en.json b/src/components/VDiskPopup/i18n/en.json new file mode 100644 index 0000000000..4d82fa9a17 --- /dev/null +++ b/src/components/VDiskPopup/i18n/en.json @@ -0,0 +1,21 @@ +{ + "context_not-available": "not available", + "label_state": "State", + "label_storage-pool": "StoragePool", + "label_node-id": "NodeId", + "label_pdisk-id": "PDiskId", + "label_vslot-id": "VSlotId", + "label_links": "Links", + "label_vdisk": "VDisk", + "label_fresh": "Fresh", + "label_level": "Level", + "label_space": "Space", + "label_front-queues": "FrontQueues", + "label_replicated": "Replicated", + "label_progress": "Progress", + "label_remaining": "Remaining", + "label_unsync-vdisks": "UnsyncVDisks", + "label_allocated": "Allocated", + "label_read": "Read", + "label_write": "Write" +} diff --git a/src/components/VDiskPopup/i18n/index.ts b/src/components/VDiskPopup/i18n/index.ts new file mode 100644 index 0000000000..d68cbc6df9 --- /dev/null +++ b/src/components/VDiskPopup/i18n/index.ts @@ -0,0 +1,7 @@ +import {registerKeysets} from '../../../utils/i18n'; + +import en from './en.json'; + +const COMPONENT = 'ydb-vDisk-popup'; + +export const vDiskPopupKeyset = registerKeysets(COMPONENT, {en}); From f2e938406210f660118d551e49861410eacd4e7f Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Tue, 5 Aug 2025 16:08:44 +0300 Subject: [PATCH 3/3] fix: review --- .../Tenant/Diagnostics/Diagnostics.tsx | 5 ++--- src/store/reducers/tenant/tenant.ts | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/containers/Tenant/Diagnostics/Diagnostics.tsx b/src/containers/Tenant/Diagnostics/Diagnostics.tsx index e1d4c66919..3a3d4e5e93 100644 --- a/src/containers/Tenant/Diagnostics/Diagnostics.tsx +++ b/src/containers/Tenant/Diagnostics/Diagnostics.tsx @@ -10,9 +10,8 @@ import { useFeatureFlagsAvailable, useTopicDataAvailable, } from '../../../store/reducers/capabilities/hooks'; -import {useClusterBaseInfo} from '../../../store/reducers/cluster/cluster'; import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants'; -import {setDiagnosticsTab} from '../../../store/reducers/tenant/tenant'; +import {setDiagnosticsTab, useTenantBaseInfo} from '../../../store/reducers/tenant/tenant'; import type {AdditionalNodesProps, AdditionalTenantsProps} from '../../../types/additionalProps'; import {uiFactory} from '../../../uiFactory/uiFactory'; import {cn} from '../../../utils/cn'; @@ -51,7 +50,7 @@ const b = cn('kv-tenant-diagnostics'); function Diagnostics(props: DiagnosticsProps) { const {path, database, type, subType} = useCurrentSchema(); - const {control_plane: controlPlane} = useClusterBaseInfo(); + const {controlPlane} = useTenantBaseInfo(path); const containerRef = React.useRef(null); const dispatch = useTypedDispatch(); const {diagnosticsTab = TENANT_DIAGNOSTICS_TABS_IDS.overview} = useTypedSelector( diff --git a/src/store/reducers/tenant/tenant.ts b/src/store/reducers/tenant/tenant.ts index e01b02d51f..0dac9732b0 100644 --- a/src/store/reducers/tenant/tenant.ts +++ b/src/store/reducers/tenant/tenant.ts @@ -4,6 +4,7 @@ import type {PayloadAction} from '@reduxjs/toolkit'; import {DEFAULT_USER_SETTINGS, settingsManager} from '../../../services/settings'; import type {TTenantInfo} from '../../../types/api/tenant'; import {TENANT_INITIAL_PAGE_KEY} from '../../../utils/constants'; +import {useClusterNameFromQuery} from '../../../utils/hooks/useDatabaseFromQuery'; import {api} from '../api'; import {TENANT_DIAGNOSTICS_TABS_IDS, TENANT_METRICS_TABS_IDS} from './constants'; @@ -100,3 +101,18 @@ export const tenantApi = api.injectEndpoints({ }), overrideExisting: 'throw', }); + +export function useTenantBaseInfo(path: string) { + const clusterNameFromQuery = useClusterNameFromQuery(); + + const {currentData} = tenantApi.useGetTenantInfoQuery({ + path, + clusterName: clusterNameFromQuery, + }); + + const {ControlPlane} = currentData || {}; + + return { + controlPlane: ControlPlane, + }; +}