import {Flex, Text} from '@gravity-ui/uikit';
import {isNil} from 'lodash';
import {EType} from '../../../../../types/api/tenant';
import {cn} from '../../../../../utils/cn';
import {GroupedSummaryCard, SummaryCard} from './TenantStorageSummaryCard';
import type {GroupedSummaryCardRow} from './TenantStorageSummaryCard';
import {
formatOverheadValue,
formatTenantStorageApproximateMetric,
formatTenantStorageSummaryMetric,
getTenantStorageLegendValueFormatter,
getTenantStorageSegmentValueFormatters,
getTenantStorageSummaryMetricUnit,
} from './displayFormatters';
import i18n from './i18n';
import type {
TenantStorageData,
TenantStorageMediaSection,
TenantStorageSegment,
TenantStorageSummary,
TenantStorageSystemDetail,
} from './utils';
import {
getTenantStoragePhysicalDisplaySegments,
getTenantStoragePhysicalMediaBreakdown,
getTenantStorageSegmentDisplayValue,
getTenantStorageUserDataDisplaySummary,
mergeSystemDetailsByMedia,
} from './utils';
import './TenantStorageSummarySections.scss';
const b = cn('ydb-tenant-storage-summary-sections');
function getMediaSectionLabel(mediaType?: string) {
if (!mediaType || mediaType === EType.None) {
return undefined;
}
return mediaType;
}
function getUserSummaryRow({
id,
mediaLabel,
segments,
summary,
}: {
id: string;
mediaLabel?: string;
segments?: TenantStorageSegment[];
summary: TenantStorageSummary;
}): GroupedSummaryCardRow {
const metricsSize = getTenantStorageSummaryMetricUnit([
summary.available,
summary.used,
summary.quota,
]);
const {formatLegendValue, formatTooltipValue} = getTenantStorageSegmentValueFormatters(
(segments ?? []).map(getTenantStorageSegmentDisplayValue),
);
const formattedAvailableValue = summary.availableApproximate
? formatTenantStorageApproximateMetric(summary.available, metricsSize)
: formatTenantStorageSummaryMetric(summary.available, metricsSize);
const hasQuota = summary.quota !== undefined;
return {
id,
mediaLabel,
summary,
segments,
formatLegendValue,
formatTooltipValue,
tooltipTotalLabel: i18n('value_total-user-data'),
metrics: [
{
hideDivider: true,
label: i18n('field_available'),
note: summary.availableApproximate
? i18n('context_available-approximate')
: undefined,
noData: isNil(summary.available),
value: formattedAvailableValue,
},
{
label: i18n('field_used'),
value: formatTenantStorageSummaryMetric(summary.used, metricsSize),
},
{
label: i18n('field_quota'),
note: hasQuota ? undefined : i18n('alert_missing-quota-description'),
notePlacement: 'value',
noteTitle: hasQuota ? undefined : i18n('alert_missing-quota-title'),
noData: isNil(summary.quota),
value: formatTenantStorageSummaryMetric(summary.quota, metricsSize),
},
],
};
}
function renderUserSummary(summary: TenantStorageSummary, segments?: TenantStorageSegment[]) {
const row = getUserSummaryRow({id: 'user-data', summary, segments});
return (
);
}
function getPhysicalSummaryRow({
id,
mediaLabel,
segments,
summary,
systemDetails,
}: {
id: string;
mediaLabel?: string;
segments?: TenantStorageSegment[];
summary: TenantStorageSummary;
systemDetails?: TenantStorageSystemDetail[];
}): GroupedSummaryCardRow {
const metricsSize = getTenantStorageSummaryMetricUnit([
summary.available,
summary.used,
summary.total,
]);
const {formatLegendValue, formatTooltipValue} = getTenantStorageSegmentValueFormatters(
(segments ?? []).map(getTenantStorageSegmentDisplayValue),
);
const formatSystemDetailValue = getTenantStorageLegendValueFormatter(
(systemDetails ?? []).map((detail) => detail.value),
);
return {
id,
mediaLabel,
summary,
segments,
formatLegendValue,
formatSystemDetailValue,
formatTooltipValue,
tooltipTotalLabel: i18n('value_total-physical-disk-usage'),
displayNoLimit: 'filled',
systemDetails,
metrics: [
{
emphasize: true,
label: i18n('field_overhead'),
note: i18n('context_overhead-description'),
noData: isNil(summary.overhead),
value: formatOverheadValue(summary.overhead),
},
{
hideDivider: true,
label: i18n('field_available'),
noData: isNil(summary.available),
value: formatTenantStorageSummaryMetric(summary.available, metricsSize),
},
{
label: i18n('field_used'),
value: formatTenantStorageSummaryMetric(summary.used, metricsSize),
},
{
label: i18n('field_total'),
noData: isNil(summary.total),
value: formatTenantStorageSummaryMetric(summary.total, metricsSize),
},
],
};
}
function renderPhysicalSummary(
summary: TenantStorageSummary,
segments?: TenantStorageSegment[],
systemDetails?: TenantStorageSystemDetail[],
) {
const row = getPhysicalSummaryRow({id: 'physical', summary, segments, systemDetails});
return (
);
}
function getMediaSectionRows({
data,
index = 0,
section,
showMediaTypeLabel,
}: {
data: TenantStorageData;
index?: number;
section: TenantStorageMediaSection;
showMediaTypeLabel: boolean;
}) {
const mediaLabel = getMediaSectionLabel(section.mediaType);
const userDataSummary = getTenantStorageUserDataDisplaySummary({
summary: section.userData,
logicalUserData: data.logicalUserData,
useLogicalBreakdown: !showMediaTypeLabel,
physical: section.physical,
});
const userSegments = showMediaTypeLabel ? undefined : data.userDataSegments;
let physicalSegments: TenantStorageSegment[];
let systemDetails: TenantStorageSystemDetail[] | undefined;
if (section.mediaType === EType.None) {
physicalSegments = data.summary.physical.segments;
systemDetails = mergeSystemDetailsByMedia(data.systemDetailsByMedia);
} else {
const mediaBreakdown = getTenantStoragePhysicalMediaBreakdown({
allowAggregateFallback: !showMediaTypeLabel,
mediaType: section.mediaType,
physicalSegmentsByMedia: data.physicalSegmentsByMedia,
systemDetailsByMedia: data.systemDetailsByMedia,
});
physicalSegments = getTenantStoragePhysicalDisplaySegments({
segments: mediaBreakdown.segments,
used: section.physical.used,
});
systemDetails = mediaBreakdown.systemDetails;
}
return {
mediaLabel,
physical: getPhysicalSummaryRow({
id: `physical-${section.mediaType}-${index}`,
mediaLabel,
summary: section.physical,
segments: physicalSegments,
systemDetails,
}),
user: getUserSummaryRow({
id: `user-${section.mediaType}-${index}`,
mediaLabel,
summary: userDataSummary,
segments: userSegments,
}),
};
}
interface TenantStorageMediaSectionViewProps {
section: TenantStorageMediaSection;
showMediaTypeLabel: boolean;
data: TenantStorageData;
showPhysicalDiskUsage?: boolean;
}
export function TenantStorageMediaSectionView({
section,
showMediaTypeLabel,
data,
showPhysicalDiskUsage,
}: TenantStorageMediaSectionViewProps) {
const {mediaLabel, physical, user} = getMediaSectionRows({
data,
section,
showMediaTypeLabel,
});
return (
{showMediaTypeLabel && mediaLabel ? (
{mediaLabel}
) : null}
{renderUserSummary(user.summary, user.segments)}
{showPhysicalDiskUsage
? renderPhysicalSummary(physical.summary, physical.segments, physical.systemDetails)
: null}
);
}
interface TenantStorageGroupedMediaSectionsViewProps {
data: TenantStorageData;
sections: TenantStorageMediaSection[];
showPhysicalDiskUsage?: boolean;
}
export function TenantStorageGroupedMediaSectionsView({
data,
sections,
showPhysicalDiskUsage,
}: TenantStorageGroupedMediaSectionsViewProps) {
const rows = sections.map((section, index) => {
return getMediaSectionRows({
data,
index,
section,
showMediaTypeLabel: true,
});
});
return (
row.user)}
/>
{showPhysicalDiskUsage ? (
row.physical)}
/>
) : null}
);
}