diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx index 17c54fde979..3150c7e8e8e 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx @@ -19,9 +19,11 @@ import { import { DataHoverClearEvent, DataHoverEvent, + DecimalCount, FALLBACK_COLOR, Field, FieldType, + formattedValueToString, getDisplayProcessor, } from '@grafana/data'; import { Trans } from '@grafana/i18n'; @@ -439,7 +441,7 @@ export function TableNG(props: TableNGProps) { // attach JSONCell custom display function to JSONView cell type if (cellType === TableCellDisplayMode.JSONView || field.type === FieldType.other) { - field.display = displayJsonValue; + field.display = displayJsonValue(field); } // For some cells, "aligning" the cell will mean aligning the inline contents of the cell with diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts index 9109375ae17..c6060814abe 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts @@ -48,6 +48,7 @@ import { predicateByName, parseStyleJson, calculateFooterHeight, + displayJsonValue, } from './utils'; describe('TableNG utils', () => { @@ -1355,10 +1356,35 @@ describe('TableNG utils', () => { }); describe('displayJsonValue', () => { - it.todo('should parse and then stringify string values'); - it.todo('should not throw for non-serializable string values'); - it.todo('should stringify non-string values'); - it.todo('should not throw for non-serializable non-string values'); + let field: Field; + beforeEach(() => { + field = { + name: 'test', + type: FieldType.string, + config: {}, + state: { displayName: 'Test Display Name' }, + values: [], + display: (val: unknown) => ({ text: String(val), numeric: NaN }), + }; + }); + + it('should parse and then stringify string values', () => { + expect(displayJsonValue(field)('{"valid": "json"}').text).toBe('{\n "valid": "json"\n}'); + }); + + it('should not throw for non-serializable string values', () => { + expect(displayJsonValue(field)('{"invalid": "json').text).toBe('{"invalid": "json'); + }); + + it('should stringify non-string values', () => { + expect(displayJsonValue(field)(42).text).toBe('42'); + }); + + it('should use the underlying field.display method to format values and return numeric values', () => { + field.display = (val: unknown) => ({ text: `**${val}**`, numeric: Number(val), suffix: 'ms' }); + expect(displayJsonValue(field)(42).text).toBe('**42**ms'); + expect(displayJsonValue(field)(42).numeric).toBe(42); + }); }); describe('applySort', () => { diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.ts index 848f21957b0..d2dd402217d 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/utils.ts +++ b/packages/grafana-ui/src/components/Table/TableNG/utils.ts @@ -15,6 +15,7 @@ import { DisplayValueAlignmentFactors, DataFrame, DisplayProcessor, + DecimalCount, } from '@grafana/data'; import { BarGaugeDisplayMode, @@ -970,28 +971,24 @@ export function canFieldBeColorized( ); } -export const displayJsonValue: DisplayProcessor = (value: unknown): DisplayValue => { - let displayValue: string; +export const displayJsonValue: (field: Field) => DisplayProcessor = (field: Field, decimals?: DecimalCount) => { + const origDisplay = field.display!; + return (value: unknown): DisplayValue => { + let jsonText: string; - // Handle string values that might be JSON - if (typeof value === 'string') { + const displayValue = origDisplay(value, decimals); + const formattedValue = formattedValueToString(displayValue); + + // Handle string values that might be JSON try { - const parsed = JSON.parse(value); - displayValue = JSON.stringify(parsed, null, ' '); + const parsed = JSON.parse(formattedValue); + jsonText = JSON.stringify(parsed, null, ' '); } catch { - displayValue = value; // Keep original if not valid JSON + jsonText = formattedValue; // Keep original if not valid JSON } - } else { - // For non-string values, stringify them - try { - displayValue = JSON.stringify(value, null, ' '); - } catch (error) { - // Handle circular references or other stringify errors - displayValue = String(value); - } - } - return { text: displayValue, numeric: Number.NaN }; + return { ...displayValue, text: jsonText }; + }; }; export function getSummaryCellTextAlign(textAlign: TextAlign, cellType: TableCellDisplayMode): TextAlign {