import styled from '@emotion/styled';
import type {Polarity} from 'sentry/components/percentChange';
import {Tooltip} from 'sentry/components/tooltip';
import {defined} from 'sentry/utils';
import type {MetaType} from 'sentry/utils/discover/eventView';
import {getFieldRenderer} from 'sentry/utils/discover/fieldRenderers';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import {AutoSizedText} from 'sentry/views/dashboards/widgetCard/autoSizedText';
import {DifferenceToPreviousPeriodValue} from 'sentry/views/dashboards/widgets/bigNumberWidget/differenceToPreviousPeriodValue';
import type {
Meta,
TableData,
Thresholds,
} from 'sentry/views/dashboards/widgets/common/types';
import {X_GUTTER, Y_GUTTER} from '../common/settings';
import {ThresholdsIndicator} from './thresholdsIndicator';
export interface BigNumberWidgetVisualizationProps {
field: string;
value: number | string;
maximumValue?: number;
meta?: Meta;
preferredPolarity?: Polarity;
previousPeriodValue?: number | string;
thresholds?: Thresholds;
}
export function BigNumberWidgetVisualization(props: BigNumberWidgetVisualizationProps) {
const {
field,
value,
previousPeriodValue,
maximumValue = Number.MAX_VALUE,
preferredPolarity,
meta,
} = props;
const location = useLocation();
const organization = useOrganization();
// TODO: meta as MetaType is a white lie. `MetaType` doesn't know that types can be null, but they can!
const fieldRenderer = meta
? getFieldRenderer(field, meta as MetaType, false)
: renderableValue => renderableValue.toString();
const unit = meta?.units?.[field];
const type = meta?.fields?.[field];
const baggage = {
location,
organization,
unit: unit ?? undefined, // TODO: Field formatters think units can't be null but they can
};
// String values don't support differences, thresholds, max values, or anything else.
if (typeof value === 'string') {
return (
{fieldRenderer(
{
[field]: value,
},
baggage
)}
);
}
const doesValueHitMaximum = maximumValue ? value >= maximumValue : false;
const clampedValue = Math.min(value, maximumValue);
return (
{defined(props.thresholds?.max_values.max1) &&
defined(props.thresholds?.max_values.max2) && (
)}
{doesValueHitMaximum ? '>' : ''}
{fieldRenderer(
{
[field]: clampedValue,
},
baggage
)}
{defined(previousPeriodValue) &&
typeof previousPeriodValue === 'number' &&
Number.isFinite(previousPeriodValue) &&
!Number.isNaN(previousPeriodValue) &&
!doesValueHitMaximum && (
fieldRenderer(previousDatum, baggage)
}
/>
)}
);
}
function Wrapper({children}) {
return (
{children}
);
}
const AutoResizeParent = styled('div')`
position: absolute;
inset: ${Y_GUTTER} ${X_GUTTER} ${Y_GUTTER} ${X_GUTTER};
color: ${p => p.theme.headingColor};
container-type: size;
container-name: auto-resize-parent;
* {
line-height: 1;
text-align: left !important;
}
`;
const NumberAndDifferenceContainer = styled('div')`
display: flex;
align-items: flex-end;
gap: min(8px, 3cqw);
`;
const NumberContainerOverride = styled('div')`
display: inline-flex;
* {
text-overflow: clip !important;
display: inline;
white-space: nowrap;
}
`;