diff --git a/static/app/chartcuterie/dashboardsWidget.tsx b/static/app/chartcuterie/dashboardsWidget.tsx index d1d6e73643ae..960919882726 100644 --- a/static/app/chartcuterie/dashboardsWidget.tsx +++ b/static/app/chartcuterie/dashboardsWidget.tsx @@ -38,7 +38,7 @@ export const makeDashboardsWidgetCharts = ( const {thresholds} = data.widget; if ( thresholds && - (defined(thresholds.max_values.max1) || defined(thresholds.max_values.max2)) + (defined(thresholds.max_values?.max1) || defined(thresholds.max_values?.max2)) ) { extraPlottables.push( new Thresholds({ diff --git a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.spec.tsx b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.spec.tsx index d6361aaf24a9..9407b2865eff 100644 --- a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.spec.tsx +++ b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.spec.tsx @@ -11,6 +11,29 @@ const exampleThresholdsConfig: ThresholdsConfig = { }; describe('Widget Builder > ThresholdsStep', () => { + it('renders without crashing when max_values is undefined', async () => { + const onChange = jest.fn(); + const configWithoutMaxValues = { + max_values: undefined, + unit: null, + } as unknown as ThresholdsConfig; + render( + + ); + + // Component should render with empty max value inputs instead of throwing + expect(await screen.findByLabelText('First Minimum')).toBeInTheDocument(); + expect(screen.getByLabelText('First Maximum', {selector: 'input'})).toHaveValue(null); + expect(screen.getByLabelText('Second Maximum', {selector: 'input'})).toHaveValue( + null + ); + }); + it('renders thresholds step', async () => { const onChange = jest.fn(); render( diff --git a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.tsx b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.tsx index e86071db52a6..9b720fd42826 100644 --- a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.tsx +++ b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholds.tsx @@ -50,7 +50,7 @@ enum ThresholdMaxKeys { type ThresholdMaxValues = Partial>; export type ThresholdsConfig = { - max_values: ThresholdMaxValues; + max_values: ThresholdMaxValues | undefined; unit: string | null; preferredPolarity?: Polarity; }; @@ -102,8 +102,8 @@ export function Thresholds({ onPolarityChange, }: ThresholdsStepProps) { const theme = useTheme(); - const maxOneValue = thresholdsConfig?.max_values[ThresholdMaxKeys.MAX_1] ?? ''; - const maxTwoValue = thresholdsConfig?.max_values[ThresholdMaxKeys.MAX_2] ?? ''; + const maxOneValue = thresholdsConfig?.max_values?.[ThresholdMaxKeys.MAX_1] ?? ''; + const maxTwoValue = thresholdsConfig?.max_values?.[ThresholdMaxKeys.MAX_2] ?? ''; const unit = thresholdsConfig?.unit ?? dataUnit; const unitOptions = getThresholdUnitSelectOptions(dataType); diff --git a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholdsHoverWrapper.tsx b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholdsHoverWrapper.tsx index d18682d81a27..7b1e904b405c 100644 --- a/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholdsHoverWrapper.tsx +++ b/static/app/views/dashboards/widgetBuilder/buildSteps/thresholdsStep/thresholdsHoverWrapper.tsx @@ -21,10 +21,7 @@ type Props = { }; export function ThresholdsHoverWrapper({children, thresholds, type}: Props) { - const { - unit, - max_values: {max1, max2}, - } = thresholds; + const {unit, max_values: {max1, max2} = {}} = thresholds; const theme = useTheme(); const formattedUnit = unit && (type === 'duration' ? `${unit}s` : `/${unit.split('/')[1]}`); diff --git a/static/app/views/dashboards/widgetBuilder/components/thresholds.tsx b/static/app/views/dashboards/widgetBuilder/components/thresholds.tsx index 9b7ad166b3a5..b61baf0297fd 100644 --- a/static/app/views/dashboards/widgetBuilder/components/thresholds.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/thresholds.tsx @@ -83,6 +83,7 @@ export function ThresholdsSection({ } if (newThresholds) { + newThresholds.max_values ??= {}; if (value) { newThresholds.max_values[maxKey] = Number(value); } else { @@ -92,7 +93,7 @@ export function ThresholdsSection({ // Check if the value cleared all of the max values if ( - newThresholds && + newThresholds?.max_values && Object.values(newThresholds.max_values).every( nextMaxValue => !defined(nextMaxValue) ) diff --git a/static/app/views/dashboards/widgetCard/visualizationWidget.tsx b/static/app/views/dashboards/widgetCard/visualizationWidget.tsx index 3719997e8431..23ed21780293 100644 --- a/static/app/views/dashboards/widgetCard/visualizationWidget.tsx +++ b/static/app/views/dashboards/widgetCard/visualizationWidget.tsx @@ -404,8 +404,8 @@ function VisualizationWidgetContent({ ); if ( - defined(widget.thresholds?.max_values.max1) || - defined(widget.thresholds?.max_values.max2) + defined(widget.thresholds?.max_values?.max1) || + defined(widget.thresholds?.max_values?.max2) ) { plottables.push( new Thresholds({ diff --git a/static/app/views/dashboards/widgets/bigNumberWidget/bigNumberWidgetVisualization.tsx b/static/app/views/dashboards/widgets/bigNumberWidget/bigNumberWidgetVisualization.tsx index 3352172a18dc..bd567eaf11fc 100644 --- a/static/app/views/dashboards/widgets/bigNumberWidget/bigNumberWidgetVisualization.tsx +++ b/static/app/views/dashboards/widgets/bigNumberWidget/bigNumberWidgetVisualization.tsx @@ -105,14 +105,14 @@ function BigNumberWidgetVisualizationInner(props: BigNumberWidgetVisualizationPr return ( - {defined(props.thresholds?.max_values.max1) && + {defined(props.thresholds?.max_values?.max1) && defined(props.thresholds?.max_values.max2) && (