From fc12a38156e117e43e89b301b58df59408a98928 Mon Sep 17 00:00:00 2001 From: Valerii Sidorenko Date: Thu, 10 Oct 2024 13:48:58 +0200 Subject: [PATCH] feat(VDisk): show VDisk donors inside popup (#1422) --- src/components/VDisk/VDisk.scss | 2 ++ src/components/VDisk/VDisk.tsx | 31 ++---------------- src/components/VDisk/VDiskWithDonorsStack.tsx | 4 +-- src/components/VDisk/utils.ts | 32 +++++++++++++++++++ src/components/VDiskPopup/VDiskPopup.tsx | 28 ++++++++++++++++ src/containers/Storage/Disks/Disks.tsx | 4 +-- src/containers/Storage/PDisk/PDisk.tsx | 10 ++---- .../__test__/calculateVDiskSeverity.test.ts | 3 +- src/utils/disks/calculateVDiskSeverity.ts | 5 ++- 9 files changed, 75 insertions(+), 44 deletions(-) create mode 100644 src/components/VDisk/utils.ts diff --git a/src/components/VDisk/VDisk.scss b/src/components/VDisk/VDisk.scss index aab1c4e3e..4e76ac289 100644 --- a/src/components/VDisk/VDisk.scss +++ b/src/components/VDisk/VDisk.scss @@ -2,6 +2,8 @@ border-radius: 4px; // to match interactive area with disk shape &__content { + display: block; + border-radius: 4px; // to match interactive area with disk shape } } diff --git a/src/components/VDisk/VDisk.tsx b/src/components/VDisk/VDisk.tsx index 9cc6d6272..cc59cffb8 100644 --- a/src/components/VDisk/VDisk.tsx +++ b/src/components/VDisk/VDisk.tsx @@ -1,16 +1,13 @@ import React from 'react'; -import {STRUCTURE} from '../../containers/Node/NodePages'; -import routes, {createHref, getVDiskPagePath} from '../../routes'; -import {useDiskPagesAvailable} from '../../store/reducers/capabilities/hooks'; -import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; -import {isFullVDiskData} from '../../utils/disks/helpers'; import type {PreparedVDisk} from '../../utils/disks/types'; import {DiskStateProgressBar} from '../DiskStateProgressBar/DiskStateProgressBar'; import {InternalLink} from '../InternalLink'; import {VDiskPopup} from '../VDiskPopup/VDiskPopup'; +import {getVDiskLink} from './utils'; + import './VDisk.scss'; const b = cn('ydb-vdisk-component'); @@ -34,10 +31,6 @@ export const VDisk = ({ onHidePopup, progressBarClassName, }: VDiskProps) => { - const isFullData = isFullVDiskData(data); - - const diskPagesAvailable = useDiskPagesAvailable(); - const [isPopupVisible, setIsPopupVisible] = React.useState(false); const anchor = React.useRef(null); @@ -52,25 +45,7 @@ export const VDisk = ({ onHidePopup?.(); }; - let vDiskPath: string | undefined; - - if ( - diskPagesAvailable && - valueIsDefined(data.VDiskSlotId) && - valueIsDefined(data.PDiskId) && - valueIsDefined(data.NodeId) - ) { - vDiskPath = getVDiskPagePath(data.VDiskSlotId, data.PDiskId, data.NodeId); - } else if (valueIsDefined(data.NodeId) && isFullData) { - vDiskPath = createHref( - routes.node, - {id: data.NodeId, activeTab: STRUCTURE}, - { - pdiskId: data.PDiskId, - vdiskId: data.StringifiedId, - }, - ); - } + const vDiskPath = getVDiskLink(data); return ( diff --git a/src/components/VDisk/VDiskWithDonorsStack.tsx b/src/components/VDisk/VDiskWithDonorsStack.tsx index 6b4bc6106..f1d971f11 100644 --- a/src/components/VDisk/VDiskWithDonorsStack.tsx +++ b/src/components/VDisk/VDiskWithDonorsStack.tsx @@ -18,12 +18,12 @@ export function VDiskWithDonorsStack({ stackClassName, ...restProps }: VDiskWithDonorsStackProps) { - const donors = data?.Donors; + const {Donors: donors, ...restData} = data || {}; const content = donors && donors.length > 0 ? ( - + {donors.map((donor) => { const isFullData = isFullVDiskData(donor); diff --git a/src/components/VDisk/utils.ts b/src/components/VDisk/utils.ts new file mode 100644 index 000000000..da81251c4 --- /dev/null +++ b/src/components/VDisk/utils.ts @@ -0,0 +1,32 @@ +import {STRUCTURE} from '../../containers/Node/NodePages'; +import routes, {createHref, getVDiskPagePath} from '../../routes'; +import type {TVDiskStateInfo, TVSlotId} from '../../types/api/vdisk'; +import {valueIsDefined} from '../../utils'; +import {stringifyVdiskId} from '../../utils/dataFormatters/dataFormatters'; +import {isFullVDiskData} from '../../utils/disks/helpers'; + +export function getVDiskLink(data: TVDiskStateInfo | TVSlotId) { + let vDiskPath: string | undefined; + + const isFullData = isFullVDiskData(data); + const VDiskSlotId = isFullData ? data.VDiskSlotId : data.VSlotId; + + if ( + valueIsDefined(VDiskSlotId) && + valueIsDefined(data.PDiskId) && + valueIsDefined(data.NodeId) + ) { + vDiskPath = getVDiskPagePath(VDiskSlotId, data.PDiskId, data.NodeId); + } else if (valueIsDefined(data.NodeId) && isFullVDiskData(data)) { + vDiskPath = createHref( + routes.node, + {id: data.NodeId, activeTab: STRUCTURE}, + { + pdiskId: data.PDiskId, + vdiskId: stringifyVdiskId(data.VDiskId), + }, + ); + } + + return vDiskPath; +} diff --git a/src/components/VDiskPopup/VDiskPopup.tsx b/src/components/VDiskPopup/VDiskPopup.tsx index e2a587d00..48c459e79 100644 --- a/src/components/VDiskPopup/VDiskPopup.tsx +++ b/src/components/VDiskPopup/VDiskPopup.tsx @@ -8,13 +8,16 @@ import {EFlag} from '../../types/api/enums'; import {valueIsDefined} from '../../utils'; import {cn} from '../../utils/cn'; import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'; +import {stringifyVdiskId} from '../../utils/dataFormatters/dataFormatters'; import {isFullVDiskData} from '../../utils/disks/helpers'; import type {PreparedVDisk, UnavailableDonor} from '../../utils/disks/types'; import {useTypedSelector} from '../../utils/hooks'; import {bytesToGB, bytesToSpeed} from '../../utils/utils'; import type {InfoViewerItem} from '../InfoViewer'; import {InfoViewer} from '../InfoViewer'; +import {InternalLink} from '../InternalLink'; import {preparePDiskData} from '../PDiskPopup/PDiskPopup'; +import {getVDiskLink} from '../VDisk/utils'; import './VDiskPopup.scss'; @@ -146,6 +149,30 @@ export const VDiskPopup = ({data, ...props}: VDiskPopupProps) => { [data, nodeHost, isFullData], ); + const donorsInfo: InfoViewerItem[] = []; + if ('Donors' in data && data.Donors) { + const donors = data.Donors; + for (const donor of donors) { + const isFullDonorData = isFullVDiskData(donor); + donorsInfo.push({ + label: 'VDisk', + value: ( + + {stringifyVdiskId( + isFullDonorData + ? donor.VDiskId + : { + NodeId: donor.NodeId, + PDiskId: donor.PDiskId, + VSlotId: donor.VSlotId, + }, + )} + + ), + }); + } + } + return ( { {data.DonorMode && } {pdiskInfo && } + {donorsInfo.length > 0 && } ); }; diff --git a/src/containers/Storage/Disks/Disks.tsx b/src/containers/Storage/Disks/Disks.tsx index 3e96c5504..fa0dbc7c3 100644 --- a/src/containers/Storage/Disks/Disks.tsx +++ b/src/containers/Storage/Disks/Disks.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import {VDiskWithDonorsStack} from '../../../components/VDisk/VDiskWithDonorsStack'; +import {VDisk} from '../../../components/VDisk/VDisk'; import {cn} from '../../../utils/cn'; import {getPDiskId} from '../../../utils/disks/helpers'; import type {PreparedVDisk} from '../../../utils/disks/types'; @@ -72,7 +72,7 @@ function VDiskItem({vDisk, highlightedVDisk, inactive, setHighlightedVDisk}: Dis }} className={b('vdisk-item')} > - { const [isPopupVisible, setIsPopupVisible] = React.useState(false); - const diskPagesAvailable = useDiskPagesAvailable(); - const anchor = React.useRef(null); const {NodeId, PDiskId} = data; @@ -75,10 +72,9 @@ export const PDisk = ({ flexGrow: Number(vdisk.AllocatedSize) || 1, }} > - @@ -94,7 +90,7 @@ export const PDisk = ({ pDiskPath = createHref(routes.node, {id: NodeId, activeTab: STRUCTURE}, {pdiskId: PDiskId}); } - if (pDiskIdsDefined && diskPagesAvailable) { + if (pDiskIdsDefined) { pDiskPath = getPDiskPagePath(PDiskId, NodeId); } diff --git a/src/utils/disks/__test__/calculateVDiskSeverity.test.ts b/src/utils/disks/__test__/calculateVDiskSeverity.test.ts index 22a9ebe5e..3dddca95d 100644 --- a/src/utils/disks/__test__/calculateVDiskSeverity.test.ts +++ b/src/utils/disks/__test__/calculateVDiskSeverity.test.ts @@ -148,8 +148,7 @@ describe('VDisk state', () => { DonorMode: true, }); - expect(severity1).not.toEqual(DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Blue); - expect(severity1).toEqual(DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Green); + expect(severity1).toEqual(DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Blue); expect(severity2).toEqual(DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Yellow); expect(severity3).toEqual(DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Red); }); diff --git a/src/utils/disks/calculateVDiskSeverity.ts b/src/utils/disks/calculateVDiskSeverity.ts index 2e5715f3b..54d71b89f 100644 --- a/src/utils/disks/calculateVDiskSeverity.ts +++ b/src/utils/disks/calculateVDiskSeverity.ts @@ -13,7 +13,7 @@ export function calculateVDiskSeverity(vDisk: TVDiskStateInfo) { return NOT_AVAILABLE_SEVERITY; } - const {DiskSpace, VDiskState, FrontQueues, Replicated, DonorMode} = vDisk; + const {DiskSpace, VDiskState, FrontQueues, Replicated} = vDisk; // if the disk is not available, this determines its status severity regardless of other features if (!VDiskState) { @@ -30,8 +30,7 @@ export function calculateVDiskSeverity(vDisk: TVDiskStateInfo) { let severity = Math.max(DiskSpaceSeverity, VDiskSpaceSeverity, FrontQueuesSeverity); // donors are always in the not replicated state since they are leftovers - // painting them blue is useless - if (!Replicated && !DonorMode && severity === DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Green) { + if (!Replicated && severity === DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Green) { severity = DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Blue; }