Transforms: Fix field matching in Format time, and add tpl var interpolation (#84239)

This commit is contained in:
Leon Sorokin 2024-03-12 17:55:23 -05:00 committed by GitHub
parent 220fea966b
commit 608b40b2a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 40 deletions

View File

@ -2,7 +2,7 @@ import { toDataFrame } from '../../dataframe/processDataFrame';
import { FieldType } from '../../types/dataFrame'; import { FieldType } from '../../types/dataFrame';
import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry';
import { createTimeFormatter, formatTimeTransformer } from './formatTime'; import { applyFormatTime, formatTimeTransformer } from './formatTime';
describe('Format Time Transformer', () => { describe('Format Time Transformer', () => {
beforeAll(() => { beforeAll(() => {
@ -16,7 +16,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc', timezone: 'utc',
}; };
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({ const frame = toDataFrame({
fields: [ fields: [
{ {
@ -27,8 +26,32 @@ describe('Format Time Transformer', () => {
], ],
}); });
const newFrame = formatter(frame.fields); const newFrames = applyFormatTime(options, [frame]);
expect(newFrame[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']); expect(newFrames[0].fields[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']);
});
it('will match on getFieldDisplayName', () => {
const options = {
timeField: 'Created',
outputFormat: 'YYYY-MM',
timezone: 'utc',
};
const frame = toDataFrame({
fields: [
{
name: 'created',
type: FieldType.time,
values: [1612939600000, 1689192000000, 1682025600000, 1690328089000, 1691011200000],
config: {
displayName: 'Created',
},
},
],
});
const newFrames = applyFormatTime(options, [frame]);
expect(newFrames[0].fields[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']);
}); });
it('will handle formats with times', () => { it('will handle formats with times', () => {
@ -38,7 +61,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc', timezone: 'utc',
}; };
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({ const frame = toDataFrame({
fields: [ fields: [
{ {
@ -49,8 +71,8 @@ describe('Format Time Transformer', () => {
], ],
}); });
const newFrame = formatter(frame.fields); const newFrames = applyFormatTime(options, [frame]);
expect(newFrame[0].values).toEqual([ expect(newFrames[0].fields[0].values).toEqual([
'2021-02 6:46:40 am', '2021-02 6:46:40 am',
'2023-07 8:00:00 pm', '2023-07 8:00:00 pm',
'2023-04 9:20:00 pm', '2023-04 9:20:00 pm',
@ -66,7 +88,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc', timezone: 'utc',
}; };
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({ const frame = toDataFrame({
fields: [ fields: [
{ {
@ -77,8 +98,8 @@ describe('Format Time Transformer', () => {
], ],
}); });
const newFrame = formatter(frame.fields); const newFrames = applyFormatTime(options, [frame]);
expect(newFrame[0].values).toEqual([ expect(newFrames[0].fields[0].values).toEqual([
'2021-02 6:46:40 am', '2021-02 6:46:40 am',
'2023-07 8:00:00 pm', '2023-07 8:00:00 pm',
'2023-04 9:20:00 pm', '2023-04 9:20:00 pm',

View File

@ -2,8 +2,9 @@ import { map } from 'rxjs/operators';
import { TimeZone } from '@grafana/schema'; import { TimeZone } from '@grafana/schema';
import { DataFrame, Field, TransformationApplicabilityLevels } from '../../types'; import { cacheFieldDisplayNames } from '../../field';
import { DataTransformerInfo } from '../../types/transformations'; import { DataFrame, TransformationApplicabilityLevels } from '../../types';
import { DataTransformContext, DataTransformerInfo } from '../../types/transformations';
import { fieldToStringField } from './convertFieldType'; import { fieldToStringField } from './convertFieldType';
import { DataTransformerID } from './ids'; import { DataTransformerID } from './ids';
@ -34,21 +35,10 @@ export const formatTimeTransformer: DataTransformerInfo<FormatTimeTransformerOpt
}, },
isApplicableDescription: isApplicableDescription:
'The Format time transformation requires a time field to work. No time field could be found.', 'The Format time transformation requires a time field to work. No time field could be found.',
operator: (options) => (source) => operator: (options, ctx) => (source) =>
source.pipe( source.pipe(
map((data) => { map((data) => {
// If a field and a format are configured return applyFormatTime(options, data, ctx);
// then format the time output
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
if (!Array.isArray(data) || data.length === 0) {
return data;
}
return data.map((frame) => ({
...frame,
fields: formatter(frame.fields),
}));
}) })
), ),
}; };
@ -56,21 +46,27 @@ export const formatTimeTransformer: DataTransformerInfo<FormatTimeTransformerOpt
/** /**
* @internal * @internal
*/ */
export const createTimeFormatter = (timeField: string, outputFormat: string, timezone: string) => (fields: Field[]) => { export const applyFormatTime = (
return fields.map((field) => { { timeField, outputFormat, timezone }: FormatTimeTransformerOptions,
// Find the configured field data: DataFrame[],
if (field.name === timeField) { ctx?: DataTransformContext
// Update values to use the configured format ) => {
let formattedField = null; if (!Array.isArray(data) || data.length === 0) {
if (timezone) { return data;
formattedField = fieldToStringField(field, outputFormat, { timeZone: timezone }); }
} else {
formattedField = fieldToStringField(field, outputFormat); cacheFieldDisplayNames(data);
outputFormat = ctx?.interpolate(outputFormat) ?? outputFormat;
return data.map((frame) => ({
...frame,
fields: frame.fields.map((field) => {
if (field.state?.displayName === timeField) {
field = fieldToStringField(field, outputFormat, { timeZone: timezone });
} }
return formattedField; return field;
} }),
}));
return field;
});
}; };