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 { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry';
import { createTimeFormatter, formatTimeTransformer } from './formatTime';
import { applyFormatTime, formatTimeTransformer } from './formatTime';
describe('Format Time Transformer', () => {
beforeAll(() => {
@ -16,7 +16,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
@ -27,8 +26,32 @@ describe('Format Time Transformer', () => {
],
});
const newFrame = formatter(frame.fields);
expect(newFrame[0].values).toEqual(['2021-02', '2023-07', '2023-04', '2023-07', '2023-08']);
const newFrames = applyFormatTime(options, [frame]);
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', () => {
@ -38,7 +61,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
@ -49,8 +71,8 @@ describe('Format Time Transformer', () => {
],
});
const newFrame = formatter(frame.fields);
expect(newFrame[0].values).toEqual([
const newFrames = applyFormatTime(options, [frame]);
expect(newFrames[0].fields[0].values).toEqual([
'2021-02 6:46:40 am',
'2023-07 8:00:00 pm',
'2023-04 9:20:00 pm',
@ -66,7 +88,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};
const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
@ -77,8 +98,8 @@ describe('Format Time Transformer', () => {
],
});
const newFrame = formatter(frame.fields);
expect(newFrame[0].values).toEqual([
const newFrames = applyFormatTime(options, [frame]);
expect(newFrames[0].fields[0].values).toEqual([
'2021-02 6:46:40 am',
'2023-07 8:00: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 { DataFrame, Field, TransformationApplicabilityLevels } from '../../types';
import { DataTransformerInfo } from '../../types/transformations';
import { cacheFieldDisplayNames } from '../../field';
import { DataFrame, TransformationApplicabilityLevels } from '../../types';
import { DataTransformContext, DataTransformerInfo } from '../../types/transformations';
import { fieldToStringField } from './convertFieldType';
import { DataTransformerID } from './ids';
@ -34,21 +35,10 @@ export const formatTimeTransformer: DataTransformerInfo<FormatTimeTransformerOpt
},
isApplicableDescription:
'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(
map((data) => {
// If a field and a format are configured
// 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),
}));
return applyFormatTime(options, data, ctx);
})
),
};
@ -56,21 +46,27 @@ export const formatTimeTransformer: DataTransformerInfo<FormatTimeTransformerOpt
/**
* @internal
*/
export const createTimeFormatter = (timeField: string, outputFormat: string, timezone: string) => (fields: Field[]) => {
return fields.map((field) => {
// Find the configured field
if (field.name === timeField) {
// Update values to use the configured format
let formattedField = null;
if (timezone) {
formattedField = fieldToStringField(field, outputFormat, { timeZone: timezone });
} else {
formattedField = fieldToStringField(field, outputFormat);
export const applyFormatTime = (
{ timeField, outputFormat, timezone }: FormatTimeTransformerOptions,
data: DataFrame[],
ctx?: DataTransformContext
) => {
if (!Array.isArray(data) || data.length === 0) {
return data;
}
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;
}),
}));
};