import type {ReactText} from 'react';
import {Fragment} from 'react';
import styled from '@emotion/styled';
import Duration from 'sentry/components/duration';
import FileSize from 'sentry/components/fileSize';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import {PercentChange, type Polarity} from 'sentry/components/percentChange';
import {Tooltip} from 'sentry/components/tooltip';
import {space} from 'sentry/styles/space';
import {defined} from 'sentry/utils';
import {
type CountUnit,
CurrencyUnit,
DurationUnit,
type PercentageUnit,
type PercentChangeUnit,
RateUnit,
SizeUnit,
} from 'sentry/utils/discover/fields';
import {formatAbbreviatedNumber, formatRate} from 'sentry/utils/formatters';
import {formatPercentage} from 'sentry/utils/number/formatPercentage';
type Unit =
| DurationUnit.MILLISECOND
| SizeUnit.BYTE
| RateUnit
| CountUnit
| PercentageUnit
| PercentChangeUnit
| CurrencyUnit;
interface Props {
title: string;
unit: Unit;
value: ReactText | undefined;
isLoading?: boolean;
preferredPolarity?: Polarity;
tooltip?: React.ReactNode;
}
export function MetricReadout(props: Props) {
return (
{props.title}
);
}
function ReadoutContent({unit, value, tooltip, isLoading, preferredPolarity}: Props) {
if (isLoading) {
return (
);
}
if (!defined(value)) {
return --;
}
let renderedValue: React.ReactNode;
if (isARateUnit(unit)) {
renderedValue = (
{formatRate(typeof value === 'string' ? parseFloat(value) : value, unit, {
minimumValue: MINIMUM_RATE_VALUE,
})}
);
}
if (unit === DurationUnit.MILLISECOND) {
// TODO: Implement other durations
renderedValue = (
);
}
if (unit === SizeUnit.BYTE) {
// TODO: Implement other sizes
renderedValue = (
);
}
if (unit === 'count') {
renderedValue = (
{formatAbbreviatedNumber(typeof value === 'string' ? parseInt(value, 10) : value)}
);
}
if (unit === CurrencyUnit.USD) {
const numericValue = typeof value === 'string' ? parseFloat(value) : value;
if (numericValue <= 1) {
renderedValue = (
US ${numericValue.toFixed(3)}
);
} else {
renderedValue = (
US ${formatAbbreviatedNumber(numericValue)}
);
}
}
if (unit === 'percentage') {
renderedValue = (
{formatPercentage(
typeof value === 'string' ? parseFloat(value) : value,
undefined,
{minimumValue: MINIMUM_PERCENTAGE_VALUE}
)}
);
}
if (unit === 'percent_change') {
renderedValue = (
);
}
if (tooltip) {
return (
{renderedValue}
);
}
return {renderedValue};
}
const MINIMUM_RATE_VALUE = 0.01;
const MINIMUM_PERCENTAGE_VALUE = 0.0001; // 0.01%
const NumberContainer = styled('div')<{align: 'left' | 'right'}>`
text-align: ${p => p.align};
font-variant-numeric: tabular-nums;
`;
const LoadingContainer = styled('div')<{align: 'left' | 'right'}>`
display: flex;
justify-content: ${p => (p.align === 'right' ? 'flex-end' : 'flex-start')};
align-items: center;
`;
function isARateUnit(unit: string): unit is RateUnit {
return (Object.values(RateUnit) as string[]).includes(unit);
}
const ReadoutWrapper = styled('div')`
flex-grow: 0;
min-width: 0;
word-break: break-word;
`;
const ReadoutTitle = styled('h3')<{alignment: 'left' | 'right'}>`
color: ${p => p.theme.gray300};
font-size: ${p => p.theme.fontSizeMedium};
margin: 0;
white-space: nowrap;
height: ${space(3)};
text-align: ${p => p.alignment};
`;
const ReadoutContentWrapper = styled('h4')<{alignment: 'left' | 'right'}>`
margin: 0;
font-weight: ${p => p.theme.fontWeightNormal};
text-align: ${p => p.alignment};
`;