From e9b0b090c615645feeb8904771d7df204c34cce1 Mon Sep 17 00:00:00 2001 From: Alex Spencer <52186778+alexjonspencer1@users.noreply.github.com> Date: Tue, 20 May 2025 07:04:47 -0700 Subject: [PATCH] [release-11.6.2] ConvertFieldType: Update "join with" to work on array of strings (#105482) * ConvertFieldType: Update "join with" to work on array of strings (#105074) * fix: update join with to work on array of strings * chore: simplify * chore: cleanup * chore: add tests! * fix: more robust check (cherry picked from commit b77bf9889045976fc54be64b356e4b58005e1cfc) * fix: add width --- .../transformers/convertFieldType.test.ts | 34 ++++++++++++++++++- .../transformers/convertFieldType.ts | 5 ++- .../ConvertFieldTypeTransformerEditor.tsx | 12 +++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/grafana-data/src/transformations/transformers/convertFieldType.test.ts b/packages/grafana-data/src/transformations/transformers/convertFieldType.test.ts index a41e61f556f..b0e29ea9c8b 100644 --- a/packages/grafana-data/src/transformations/transformers/convertFieldType.test.ts +++ b/packages/grafana-data/src/transformations/transformers/convertFieldType.test.ts @@ -359,7 +359,7 @@ describe('field convert types transformer', () => { ]); }); - it('will support custom join separators', () => { + it('will support custom join separators for field type other', () => { const options = { conversions: [{ targetField: 'vals', destinationType: FieldType.string, joinWith: '|' }], }; @@ -391,6 +391,38 @@ describe('field convert types transformer', () => { ]); }); + it('will support custom join separators for field type string', () => { + const options = { + conversions: [{ targetField: 'string_arrays', destinationType: FieldType.string, joinWith: '&' }], + }; + + const stringArrayValues = toDataFrame({ + fields: [ + { + name: 'string_arrays', + type: FieldType.string, + values: [ + ['a', 'b', 'c'], + ['d', 'e', 'f'], + ], + }, + ], + }); + + const stringified = convertFieldTypes(options, [stringArrayValues]); + expect( + stringified[0].fields.map(({ type, values }) => ({ + type, + values, + })) + ).toEqual([ + { + type: FieldType.string, + values: ['a&b&c', 'd&e&f'], + }, + ]); + }); + it('will convert time fields to strings', () => { const options = { conversions: [{ targetField: 'time', destinationType: FieldType.string, dateFormat: 'YYYY-MM' }], diff --git a/packages/grafana-data/src/transformations/transformers/convertFieldType.ts b/packages/grafana-data/src/transformations/transformers/convertFieldType.ts index 3b3967a68b5..4e90e67a84c 100644 --- a/packages/grafana-data/src/transformations/transformers/convertFieldType.ts +++ b/packages/grafana-data/src/transformations/transformers/convertFieldType.ts @@ -210,12 +210,15 @@ export function fieldToStringField( values = values.map((v) => dateTimeParse(v, parseOptions).format(dateFormat)); break; + // Handle both "string" and "other" types to ensure compatibility across Grafana versions (10 & 11) + // In some cases fields are classified as 'other' in Grafana 10 but as 'string' in Grafana 11 + case FieldType.string: case FieldType.other: values = values.map((v) => { if (joinWith?.length && Array.isArray(v)) { return v.join(joinWith); } - return JSON.stringify(v); // will quote strings and avoid "object" + return field.type === FieldType.other ? JSON.stringify(v) : `${v}`; }); break; diff --git a/public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx b/public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx index 77a981540e4..612a27a11e2 100644 --- a/public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx +++ b/public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx @@ -132,6 +132,14 @@ export const ConvertFieldTypeTransformerEditor = ({ <> {options.conversions.map((c: ConvertFieldTypeOptions, idx: number) => { const targetField = findField(input?.[0], c.targetField); + + // Show "Join with" input when: + // - A join value exists (maintains backward compatibility) + // - Target field type is 'other' (Grafana 10) or 'string' (Grafana 11) + // This ensures consistent UI across versions where arrays may be classified differently. + const shouldRenderJoinWith = + c.joinWith?.length || (targetField?.type && [FieldType.other, FieldType.string].includes(targetField.type)); + return (
@@ -167,9 +175,9 @@ export const ConvertFieldTypeTransformerEditor = ({ )} {c.destinationType === FieldType.string && ( <> - {(c.joinWith?.length || targetField?.type === FieldType.other) && ( + {shouldRenderJoinWith && ( - + )} {targetField?.type === FieldType.time && (