Skip to content

Commit

Permalink
feat(dashboards): Add string value support to BigNumberWidget (#79293)
Browse files Browse the repository at this point in the history
That's right, it's _actually_ a `BigValueWidget`. Some fields (notably
`timestamp`) can be queries for big numbers and they should work! This
PR adds handling for possible string data.
  • Loading branch information
gggritso authored Oct 18, 2024
1 parent 6a8ff4c commit 97ed590
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,47 @@ describe('BigNumberWidget', () => {
expect(screen.getByText('Value is not a finite number.')).toBeInTheDocument();
});

it('Formats dates', () => {
render(
<BigNumberWidget
data={[
{
'max(timestamp)': '2024-10-17T16:08:07+00:00',
},
]}
meta={{
fields: {
'max(timestamp)': 'date',
},
units: {
'max(timestamp)': null,
},
}}
/>
);

expect(screen.getByText('Oct 17, 2024 4:08:07 PM UTC')).toBeInTheDocument();
});

it('Renders strings', () => {
render(
<BigNumberWidget
data={[
{
'any(transaction)': '/api/0/fetch',
},
]}
meta={{
fields: {
'max(timestamp)': 'string',
},
}}
/>
);

expect(screen.getByText('/api/0/fetch')).toBeInTheDocument();
});

it('Formats duration data', () => {
render(
<BigNumberWidget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export default storyBook(BigNumberWidget, story => {
visualization shows a tooltip with the full value.
</p>

<p>
<JSXNode name="BigNumberWidget" /> also supports string values. This is not
commonly used, but it's capable of rendering timestamps and in fact most fields
defined in our field renderer pipeline
</p>

<SideBySide>
<SmallSizingWindow>
<BigNumberWidget
Expand Down Expand Up @@ -95,6 +101,25 @@ export default storyBook(BigNumberWidget, story => {
}}
/>
</SmallSizingWindow>
<SmallSizingWindow>
<BigNumberWidget
title="Latest Timestamp"
description=""
data={[
{
'max(timestamp)': '2024-10-17T16:08:07+00:00',
},
]}
meta={{
fields: {
'max(timestamp)': 'date',
},
units: {
'max(timestamp)': null,
},
}}
/>
</SmallSizingWindow>
</SideBySide>
<p>
The <code>maximumValue</code> prop allows setting the maximum displayable value.
Expand Down Expand Up @@ -139,12 +164,6 @@ export default storyBook(BigNumberWidget, story => {
<NormalWidget>
<BigNumberWidget title="Loading Count" isLoading />
</NormalWidget>
<NormalWidget>
<BigNumberWidget
title="Text"
data={[{'max(user.email)': 'bufo@example.com'}]}
/>
</NormalWidget>
<NormalWidget>
<BigNumberWidget title="Missing Count" data={[{}]} />
</NormalWidget>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ export function BigNumberWidget(props: Props) {

if (!defined(value)) {
parsingError = MISSING_DATA_MESSAGE;
} else if (!Number.isFinite(value) || Number.isNaN(value)) {
} else if (
(typeof value === 'number' && !Number.isFinite(value)) ||
Number.isNaN(value)
) {
parsingError = NON_FINITE_NUMBER_MESSAGE;
}

Expand All @@ -57,17 +60,19 @@ export function BigNumberWidget(props: Props) {
error={error}
onRetry={props.onRetry}
>
<BigNumberResizeWrapper>
<BigNumberWidgetVisualization
value={Number(value)}
previousPeriodValue={Number(previousPeriodValue)}
field={field}
maximumValue={props.maximumValue}
preferredPolarity={props.preferredPolarity}
meta={props.meta}
thresholds={props.thresholds}
/>
</BigNumberResizeWrapper>
{defined(value) && (
<BigNumberResizeWrapper>
<BigNumberWidgetVisualization
value={value}
previousPeriodValue={previousPeriodValue}
field={field}
maximumValue={props.maximumValue}
preferredPolarity={props.preferredPolarity}
meta={props.meta}
thresholds={props.thresholds}
/>
</BigNumberResizeWrapper>
)}
</WidgetFrame>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import {DEFAULT_FIELD} from '../common/settings';
import {ThresholdsIndicator} from './thresholdsIndicator';

export interface BigNumberWidgetVisualizationProps {
value: number;
value: number | string;
field?: string;
maximumValue?: number;
meta?: Meta;
preferredPolarity?: Polarity;
previousPeriodValue?: number;
previousPeriodValue?: number | string;
thresholds?: Thresholds;
}

Expand All @@ -48,9 +48,6 @@ export function BigNumberWidgetVisualization(props: BigNumberWidgetVisualization
? getFieldRenderer(field, meta as MetaType, false)
: renderableValue => renderableValue.toString();

const doesValueHitMaximum = maximumValue ? value >= maximumValue : false;
const clampedValue = Math.min(value, maximumValue);

const unit = meta?.units?.[field];
const type = meta?.fields?.[field];

Expand All @@ -60,6 +57,25 @@ export function BigNumberWidgetVisualization(props: BigNumberWidgetVisualization
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 (
<Wrapper>
<NumberAndDifferenceContainer>
{fieldRenderer(
{
[field]: value,
},
baggage
)}
</NumberAndDifferenceContainer>
</Wrapper>
);
}

const doesValueHitMaximum = maximumValue ? value >= maximumValue : false;
const clampedValue = Math.min(value, maximumValue);

return (
<Wrapper>
<NumberAndDifferenceContainer>
Expand Down Expand Up @@ -92,6 +108,7 @@ export function BigNumberWidgetVisualization(props: BigNumberWidgetVisualization
</NumberContainerOverride>

{defined(previousPeriodValue) &&
typeof previousPeriodValue === 'number' &&
Number.isFinite(previousPeriodValue) &&
!Number.isNaN(previousPeriodValue) &&
!doesValueHitMaximum && (
Expand Down

0 comments on commit 97ed590

Please sign in to comment.