Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add proper types for Node PDisk and VDisk #558

Merged
merged 3 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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