Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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(() => {
Expand All @@ -16,7 +16,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};

const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
Expand All @@ -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', () => {
Expand All @@ -38,7 +61,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};

const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
Expand All @@ -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',
Expand All @@ -66,7 +88,6 @@ describe('Format Time Transformer', () => {
timezone: 'utc',
};

const formatter = createTimeFormatter(options.timeField, options.outputFormat, options.timezone);
const frame = toDataFrame({
fields: [
{
Expand All @@ -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',
Expand Down
Expand Up @@ -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';
Expand Down Expand Up @@ -34,43 +35,38 @@ 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);
})
),
};

/**
* @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;
}

return formattedField;
}
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 field;
});
return field;
}),
}));
};