diff --git a/packages/grafana-data/src/utils/valueMappings.test.ts b/packages/grafana-data/src/utils/valueMappings.test.ts
index 2b60616d850..90686b52895 100644
--- a/packages/grafana-data/src/utils/valueMappings.test.ts
+++ b/packages/grafana-data/src/utils/valueMappings.test.ts
@@ -185,6 +185,40 @@ describe('Format value with value mappings', () => {
});
});
+describe('Range mapping with null From or null To', () => {
+ expect(
+ getValueMappingResult(
+ [
+ {
+ type: MappingType.RangeToText,
+ options: {
+ from: 0,
+ to: null,
+ result: { text: 'pos' },
+ },
+ },
+ ],
+ 100
+ )
+ ).toEqual({ text: 'pos' });
+
+ expect(
+ getValueMappingResult(
+ [
+ {
+ type: MappingType.RangeToText,
+ options: {
+ from: null,
+ to: 0,
+ result: { text: 'neg' },
+ },
+ },
+ ],
+ -100
+ )
+ ).toEqual({ text: 'neg' });
+});
+
describe('Format value with regex mappings', () => {
it('should return correct regular expression result', () => {
const value = 'www.foo.com';
diff --git a/packages/grafana-data/src/utils/valueMappings.ts b/packages/grafana-data/src/utils/valueMappings.ts
index d7ab2cf6a24..910cf55511f 100644
--- a/packages/grafana-data/src/utils/valueMappings.ts
+++ b/packages/grafana-data/src/utils/valueMappings.ts
@@ -35,13 +35,17 @@ export function getValueMappingResult(valueMappings: ValueMapping[], value: any)
continue;
}
- const isNumFrom = !isNaN(vm.options.from!);
- if (isNumFrom && valueAsNumber < vm.options.from!) {
+ const from = vm.options.from ?? -Infinity;
+
+ const isNumFrom = !isNaN(from);
+ if (isNumFrom && valueAsNumber < from) {
continue;
}
- const isNumTo = !isNaN(vm.options.to!);
- if (isNumTo && valueAsNumber > vm.options.to!) {
+ const to = vm.options.to ?? Infinity;
+
+ const isNumTo = !isNaN(to);
+ if (isNumTo && valueAsNumber > to) {
continue;
}
diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx
index c26e5a26781..bb8215ffbe6 100644
--- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx
+++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx
@@ -11,8 +11,8 @@ import { ResourcePicker } from '../ResourcePicker';
export interface ValueMappingEditRowModel {
type: MappingType;
- from?: number;
- to?: number;
+ from?: number | null;
+ to?: number | null;
pattern?: string;
key?: string;
isNew?: boolean;
@@ -149,20 +149,8 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
)}
{mapping.type === MappingType.RangeToText && (
-
-
+
+
)}
{mapping.type === MappingType.RegexToText && (
diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx
index 9bdb3ec96c8..3bbeff8882a 100644
--- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx
+++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor.tsx
@@ -51,7 +51,7 @@ export const ValueMappingsEditor = memo((props: Props) => {
{row.type === MappingType.ValueToText && row.key}
{row.type === MappingType.RangeToText && (
- [{row.from} - {row.to}]
+ [{row.from ?? '-∞'} - {row.to ?? '∞'}]
)}
{row.type === MappingType.RegexToText && row.pattern}
diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx
index 1090c942122..065f9d304fe 100644
--- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx
+++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.test.tsx
@@ -134,11 +134,11 @@ describe('ValueMappingsEditorModal', () => {
);
await selectOptionInTest(selectComponent, 'Range');
- await userEvent.clear(screen.getByPlaceholderText('Range start'));
- await userEvent.type(screen.getByPlaceholderText('Range start'), '10');
+ await userEvent.clear(screen.getByPlaceholderText('From'));
+ await userEvent.type(screen.getByPlaceholderText('From'), '10');
- await userEvent.clear(screen.getByPlaceholderText('Range end'));
- await userEvent.type(screen.getByPlaceholderText('Range end'), '20');
+ await userEvent.clear(screen.getByPlaceholderText('To'));
+ await userEvent.type(screen.getByPlaceholderText('To'), '20');
await userEvent.clear(screen.getByPlaceholderText('Optional display text'));
await userEvent.type(screen.getByPlaceholderText('Optional display text'), 'display');
diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx
index 9b970427143..199563a65fc 100644
--- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx
+++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx
@@ -218,12 +218,12 @@ export function editModelToSaveModel(rows: ValueMappingEditRowModel[]) {
}
break;
case MappingType.RangeToText:
- if (item.from != null && item.to != null) {
+ if (item.from != null || item.to != null) {
mappings.push({
type: item.type,
options: {
- from: item.from,
- to: item.to,
+ from: item.from ?? null,
+ to: item.to ?? null,
result,
},
});
@@ -279,8 +279,8 @@ export function buildEditRowModels(value: ValueMapping[]) {
createRow({
type: mapping.type,
result: mapping.options.result,
- from: mapping.options.from ?? 0,
- to: mapping.options.to ?? 0,
+ from: mapping.options.from,
+ to: mapping.options.to,
})
);
break;