Skip to content

Commit

Permalink
chore: add proper types for Node PDisk and VDisk (#558)
Browse files Browse the repository at this point in the history
  • Loading branch information
artemmufazalov authored Oct 19, 2023
1 parent ca23c14 commit f31a19a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 101 deletions.
142 changes: 74 additions & 68 deletions src/containers/Node/NodeStructure/Pdisk.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
import {useState} from 'react';
import cn from 'bem-cn-lite';
import _ from 'lodash';
import {isEmpty} from 'lodash/fp';

import {ArrowToggle, Button, Popover} from '@gravity-ui/uikit';

import DataTable, {Column, Settings} from '@gravity-ui/react-data-table';

import EntityStatus from '../../../components/EntityStatus/EntityStatus';
import InfoViewer from '../../../components/InfoViewer/InfoViewer';
import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer';
import {Icon} from '../../../components/Icon';
import {Vdisk} from './Vdisk';
import DataTable, {type Column} from '@gravity-ui/react-data-table';

import type {ValueOf} from '../../../types/common';
import type {
PreparedStructurePDisk,
PreparedStructureVDisk,
} from '../../../store/reducers/node/types';
import {EVDiskState} from '../../../types/api/vdisk';
import {bytesToGB, pad9} from '../../../utils/utils';
import {formatStorageValuesToGb} from '../../../utils/dataFormatters/dataFormatters';
import {getPDiskType} from '../../../utils/pdisk';

import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
import InfoViewer, {type InfoViewerItem} from '../../../components/InfoViewer/InfoViewer';
import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer';
import {Icon} from '../../../components/Icon';

import {Vdisk} from './Vdisk';
import {valueIsDefined} from './NodeStructure';
import {PDiskTitleBadge} from './PDiskTitleBadge';

const b = cn('kv-node-structure');

interface PDiskProps {
data: Record<string, any>;
data: PreparedStructurePDisk;
unfolded?: boolean;
id: string;
selectedVdiskId?: string;
Expand All @@ -37,8 +42,7 @@ enum VDiskTableColumnsIds {
Info = 'Info',
}

type VDiskTableColumnsIdsKeys = keyof typeof VDiskTableColumnsIds;
type VDiskTableColumnsIdsValues = typeof VDiskTableColumnsIds[VDiskTableColumnsIdsKeys];
type VDiskTableColumnsIdsValues = ValueOf<typeof VDiskTableColumnsIds>;

const vDiskTableColumnsNames: Record<VDiskTableColumnsIdsValues, string> = {
VDiskSlotId: 'Slot id',
Expand All @@ -47,39 +51,35 @@ const vDiskTableColumnsNames: Record<VDiskTableColumnsIdsValues, string> = {
Info: '',
};

interface RowType {
id: string;
[VDiskTableColumnsIds.slotId]: number;
[VDiskTableColumnsIds.VDiskState]: string;
AllocatedSize: string;
AvailableSize: string;
}

function getColumns({
pDiskId,
selectedVdiskId,
nodeHref,
}: {
pDiskId: number;
pDiskId: number | undefined;
selectedVdiskId?: string;
nodeHref?: string | null;
}) {
const columns: Column<RowType>[] = [
const columns: Column<PreparedStructureVDisk>[] = [
{
name: VDiskTableColumnsIds.slotId as string,
name: VDiskTableColumnsIds.slotId,
header: vDiskTableColumnsNames[VDiskTableColumnsIds.slotId],
width: 100,
render: ({value, row}) => {
render: ({row}) => {
let vdiskInternalViewerLink = '';

if (nodeHref && value !== undefined) {
if (nodeHref && pDiskId !== undefined && row.VDiskSlotId !== undefined) {
vdiskInternalViewerLink +=
nodeHref + 'actors/vdisks/vdisk' + pad9(pDiskId) + '_' + pad9(value);
nodeHref +
'actors/vdisks/vdisk' +
pad9(pDiskId) +
'_' +
pad9(row.VDiskSlotId);
}

return (
<div className={b('vdisk-id', {selected: row.id === selectedVdiskId})}>
<span>{value as number}</span>
<span>{row.VDiskSlotId}</span>
{vdiskInternalViewerLink && (
<Button
size="s"
Expand All @@ -96,17 +96,19 @@ function getColumns({
align: DataTable.LEFT,
},
{
name: VDiskTableColumnsIds.VDiskState as string,
name: VDiskTableColumnsIds.VDiskState,
header: vDiskTableColumnsNames[VDiskTableColumnsIds.VDiskState],
width: 70,
render: ({value}) => {
return <EntityStatus status={value === 'OK' ? 'green' : 'red'} />;
render: ({row}) => {
return (
<EntityStatus status={row.VDiskState === EVDiskState.OK ? 'green' : 'red'} />
);
},
sortAccessor: (row) => (row[VDiskTableColumnsIds.VDiskState] === 'OK' ? 1 : 0),
sortAccessor: (row) => (row.VDiskState === EVDiskState.OK ? 1 : 0),
align: DataTable.CENTER,
},
{
name: VDiskTableColumnsIds.Size as string,
name: VDiskTableColumnsIds.Size,
header: vDiskTableColumnsNames[VDiskTableColumnsIds.Size],
width: 100,
render: ({row}) => {
Expand All @@ -123,7 +125,7 @@ function getColumns({
align: DataTable.CENTER,
},
{
name: VDiskTableColumnsIds.Info as string,
name: VDiskTableColumnsIds.Info,
header: vDiskTableColumnsNames[VDiskTableColumnsIds.Info],
width: 70,
render: ({row}) => {
Expand All @@ -150,10 +152,31 @@ function getColumns({
return columns;
}

export function PDisk(props: PDiskProps) {
const [unfolded, setUnfolded] = useState(props.unfolded ?? false);
export function PDisk({
id,
data,
selectedVdiskId,
nodeHref,
unfolded: unfoldedFromProps,
}: PDiskProps) {
const [unfolded, setUnfolded] = useState(unfoldedFromProps ?? false);

const {
TotalSize = 0,
AvailableSize = 0,
Device,
Guid,
PDiskId,
Path,
Realtime,
State,
Category,
SerialNumber,
vDisks,
} = data;

const data = props.data ?? {};
const total = Number(TotalSize);
const available = Number(AvailableSize);

const onOpenPDiskDetails = () => {
setUnfolded(true);
Expand All @@ -163,15 +186,12 @@ export function PDisk(props: PDiskProps) {
};

const renderVDisks = () => {
const {selectedVdiskId, data, nodeHref} = props;
const {vDisks} = data;

return (
<DataTable
theme="yandex-cloud"
data={vDisks}
columns={getColumns({nodeHref, pDiskId: data.PDiskId, selectedVdiskId})}
settings={{...DEFAULT_TABLE_SETTINGS, dynamicRender: false} as Settings}
columns={getColumns({nodeHref, pDiskId: PDiskId, selectedVdiskId})}
settings={{...DEFAULT_TABLE_SETTINGS, dynamicRender: false}}
rowClassName={(row) => {
return row.id === selectedVdiskId ? b('selected-vdisk') : '';
}}
Expand All @@ -180,30 +200,16 @@ export function PDisk(props: PDiskProps) {
};

const renderPDiskDetails = () => {
if (_.isEmpty(data)) {
if (isEmpty(data)) {
return <div>No information about PDisk</div>;
}
const {nodeHref} = props;
const {
TotalSize,
AvailableSize,
Device,
Guid,
PDiskId,
Path,
Realtime,
State,
Category,
SerialNumber,
} = data;

let pDiskInternalViewerLink = '';

if (nodeHref) {
pDiskInternalViewerLink += nodeHref + 'actors/pdisks/pdisk' + pad9(PDiskId);
}

const pdiskInfo: any = [
const pdiskInfo: InfoViewerItem[] = [
{
label: 'PDisk Id',
value: (
Expand Down Expand Up @@ -236,19 +242,19 @@ export function PDisk(props: PDiskProps) {
}
pdiskInfo.push({
label: 'Allocated Size',
value: bytesToGB(TotalSize - AvailableSize),
value: bytesToGB(total - available),
});
pdiskInfo.push({
label: 'Available Size',
value: bytesToGB(AvailableSize),
value: bytesToGB(available),
});
if (Number(TotalSize) >= 0 && Number(AvailableSize) >= 0) {
if (total >= 0 && available >= 0) {
pdiskInfo.push({
label: 'Size',
value: (
<ProgressViewer
value={TotalSize - AvailableSize}
capacity={TotalSize}
value={total - available}
capacity={total}
formatValues={formatStorageValuesToGb}
colorizeProgress={true}
className={b('size')}
Expand Down Expand Up @@ -286,24 +292,24 @@ export function PDisk(props: PDiskProps) {
};

return (
<div className={b('pdisk')} id={props.id}>
<div className={b('pdisk')} id={id}>
<div className={b('pdisk-header')}>
<div className={b('pdisk-title-wrapper')}>
<EntityStatus status={data.Device} />
<EntityStatus status={Device} />
<PDiskTitleBadge
label="PDiskID"
value={data.PDiskId}
value={PDiskId}
className={b('pdisk-title-id')}
/>
<PDiskTitleBadge value={getPDiskType(data)} className={b('pdisk-title-type')} />
<ProgressViewer
value={data.TotalSize - data.AvailableSize}
capacity={data.TotalSize}
value={total - available}
capacity={total}
formatValues={formatStorageValuesToGb}
colorizeProgress={true}
className={b('pdisk-title-size')}
/>
<PDiskTitleBadge label="VDisks" value={data.vDisks.length} />
<PDiskTitleBadge label="VDisks" value={vDisks.length} />
</div>
<Button
onClick={unfolded ? onClosePDiskDetails : onOpenPDiskDetails}
Expand Down
42 changes: 9 additions & 33 deletions src/containers/Node/NodeStructure/Vdisk.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,19 @@
import React from 'react';
import cn from 'bem-cn-lite';

import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer';
import type {TVDiskStateInfo} from '../../../types/api/vdisk';
import {
formatStorageValuesToGb,
stringifyVdiskId,
} from '../../../utils/dataFormatters/dataFormatters';
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
import {valueIsDefined} from './NodeStructure';
import InfoViewer from '../../../components/InfoViewer/InfoViewer';
import {ProgressViewer} from '../../../components/ProgressViewer/ProgressViewer';

const b = cn('kv-node-structure');
import {valueIsDefined} from './NodeStructure';

interface VdiskProps {
AllocatedSize?: string;
DiskSpace?: string;
FrontQueues?: string;
Guid?: string;
Replicated?: boolean;
VDiskState?: string;
VDiskId?: {
GroupId: number;
GroupGeneration: number;
Ring: number;
Domain: number;
VDisk: number;
};
VDiskSlotId?: number;
Kind?: string;
SatisfactionRank?: {FreshRank: {Flag: string}; LevelRank: {Flag: string}};
AvailableSize?: string;
HasUnreadableBlobs?: boolean;
IncarnationGuid?: string;
InstanceGuid?: string;
StoragePoolName?: string;
ReadThroughput?: string;
WriteThroughput?: string;
}
const b = cn('kv-node-structure');

export function Vdisk({
AllocatedSize,
Expand All @@ -57,7 +33,7 @@ export function Vdisk({
StoragePoolName,
ReadThroughput,
WriteThroughput,
}: VdiskProps) {
}: TVDiskStateInfo) {
const vdiskInfo = [];

if (valueIsDefined(VDiskSlotId)) {
Expand All @@ -81,16 +57,16 @@ export function Vdisk({
value: <EntityStatus status={DiskSpace} />,
});
}
if (valueIsDefined(SatisfactionRank?.FreshRank.Flag)) {
if (valueIsDefined(SatisfactionRank?.FreshRank?.Flag)) {
vdiskInfo.push({
label: 'Fresh Rank Satisfaction',
value: <EntityStatus status={SatisfactionRank?.FreshRank.Flag} />,
value: <EntityStatus status={SatisfactionRank?.FreshRank?.Flag} />,
});
}
if (valueIsDefined(SatisfactionRank?.LevelRank.Flag)) {
if (valueIsDefined(SatisfactionRank?.LevelRank?.Flag)) {
vdiskInfo.push({
label: 'Level Rank Satisfaction',
value: <EntityStatus status={SatisfactionRank?.LevelRank.Flag} />,
value: <EntityStatus status={SatisfactionRank?.LevelRank?.Flag} />,
});
}
vdiskInfo.push({label: 'Replicated', value: Replicated ? 'Yes' : 'No'});
Expand Down

0 comments on commit f31a19a

Please sign in to comment.