diff --git a/public/app/plugins/panel/xychart/scatter.ts b/public/app/plugins/panel/xychart/scatter.ts index 0e23d513e7b..5ef96e4a3af 100644 --- a/public/app/plugins/panel/xychart/scatter.ts +++ b/public/app/plugins/panel/xychart/scatter.ts @@ -567,6 +567,26 @@ interface FieldColorValuesWithCache extends FieldColorValues { type GetAllValues = (values: unknown[], min?: number, max?: number) => number[]; type GetOneValue = (value: unknown, min?: number, max?: number) => number; +function getLabelForRange(from: number | null, to: number | null) { + let text: string; + + if (from != null) { + if (to != null) { + text = `${from} - ${to}`; + } else { + text = `≥ ${from}`; + } + } else { + if (to != null) { + text = `≤ ${to}`; + } else { + text = ''; + } + } + + return text; +} + /** compiler for values to palette color idxs (from thresholds, mappings, by-value gradients) */ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues { const index: EnumFieldConfig = { @@ -622,14 +642,17 @@ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues let { color, text, icon } = m.options.result; if (m.type === MappingType.RangeToText) { + let { from, to } = m.options; + text ??= getLabelForRange(from, to); + let range = []; - if (m.options.from != null) { - range.push(`v >= ${Number(m.options.from)}`); + if (from != null) { + range.push(`v >= ${Number(from)}`); } - if (m.options.to != null) { - range.push(`v <= ${Number(m.options.to)}`); + if (to != null) { + range.push(`v <= ${Number(to)}`); } if (range.length > 0) { @@ -640,11 +663,13 @@ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues let spl = m.options.match; if (spl === SpecialValueMatch.NaN) { + text ??= 'NaN'; conds += `isNaN(v)`; } else if (spl === SpecialValueMatch.NullAndNaN) { + text ??= 'null/NaN'; conds += `v == null || isNaN(v)`; } else { - conds += `v ${ + let cond = spl === SpecialValueMatch.True ? '=== true' : spl === SpecialValueMatch.False @@ -653,8 +678,10 @@ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues ? '== null' : spl === SpecialValueMatch.Empty ? '=== ""' - : '== null' - }`; + : '== null'; + + conds += `v ${cond}`; + text ??= cond.replace(/[= ]+/g, ''); } let idx = indexOf(color, text, icon); @@ -666,7 +693,7 @@ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues } conds += '-1'; // ?? what default here? null? FALLBACK_COLOR? - } else if (f.config.color?.mode === FieldColorModeId.Thresholds) { + } else if (f.config.color?.mode === FieldColorModeId.Thresholds && (f.config.thresholds?.steps.length ?? 0) > 1) { if (f.config.thresholds?.mode === ThresholdsMode.Absolute) { let steps = f.config.thresholds.steps; let lasti = steps.length - 1; @@ -678,8 +705,8 @@ export function getEnumConfig(f: Field, theme: GrafanaTheme2): FieldColorValues conds += '0'; index.color = steps.map((s) => getHex8Color(s.color, theme)); - index.text = Array(steps.length).fill(''); - index.icon = index.text!.slice(); + index.text = steps.map((s, i) => (i === 0 ? `< ${steps[i + 1].value}` : getLabelForRange(s.value, null))); + index.icon = Array(steps.length).fill(''); } else { // TODO: percent thresholds? } diff --git a/public/app/plugins/panel/xychart/utils.test.ts b/public/app/plugins/panel/xychart/utils.test.ts index cba4897126d..5523bf43b3a 100644 --- a/public/app/plugins/panel/xychart/utils.test.ts +++ b/public/app/plugins/panel/xychart/utils.test.ts @@ -31,7 +31,7 @@ describe('value mapping function', () => { }; const { index, getAll } = getEnumConfig(field, createTheme()); - expect(index).toEqual({ color: ['#73bf69ff', '#f2495cff'], icon: ['', ''], text: ['', ''] }); + expect(index).toEqual({ color: ['#73bf69ff', '#f2495cff'], icon: ['', ''], text: ['< 30', '≥ 30'] }); expect(getAll(field.values)).toEqual([0, 0, 0, 1, 1, 1]); });