diff --git a/packages/grafana-data/src/transformations/transformers/calculateField.ts b/packages/grafana-data/src/transformations/transformers/calculateField.ts index 28b60fc5cdc..908e019ff8a 100644 --- a/packages/grafana-data/src/transformations/transformers/calculateField.ts +++ b/packages/grafana-data/src/transformations/transformers/calculateField.ts @@ -3,6 +3,7 @@ import { map } from 'rxjs/operators'; import { getTimeField } from '../../dataframe/processDataFrame'; import { getFieldDisplayName } from '../../field/fieldState'; +import { ScopedVars } from '../../types/ScopedVars'; import { NullValueMode } from '../../types/data'; import { DataFrame, FieldType, Field } from '../../types/dataFrame'; import { DataTransformContext, DataTransformerInfo } from '../../types/transformations'; @@ -75,6 +76,7 @@ interface IndexOptions { interface TemplateExpressionOptions { expression: string; + replaceFn: Function; } const defaultReduceOptions: ReduceOptions = { @@ -257,7 +259,42 @@ export const calculateFieldTransformer: DataTransformerInfo { + if (options.template?.expression !== undefined) { + let newFieldVals: Array; + if (options.template?.replaceFn !== undefined) { + newFieldVals = Array.from({ length: frame.length }, (_, i) => { + const fieldVars: ScopedVars = {}; + frame.fields.forEach((field) => { + fieldVars[field.name] = { + value: field.values[i], + }; + }); + const outVal = options.template?.replaceFn(options.template.expression, fieldVars); + console.log('replacefn exists', i, outVal); + return outVal; + }); + } else { + console.log('replacefn not exists'); + newFieldVals = Array.from({ length: frame.length }, () => { + return options.template?.expression; + }); + } + console.log('newFieldVals', newFieldVals); + const f: Field = { + name: options.alias ?? 'Field', + type: FieldType.string, + values: newFieldVals, + config: {}, + }; + return { + ...frame, + fields: options.replaceFields ? [f] : [...frame.fields, f], + }; + } else { + return frame; + } + }); } // Nothing configured diff --git a/public/app/features/transformers/editors/CalculateFieldTransformerEditor/TemplateExpressionOptionsEditor.tsx b/public/app/features/transformers/editors/CalculateFieldTransformerEditor/TemplateExpressionOptionsEditor.tsx index 4023917b198..8956d6943c2 100644 --- a/public/app/features/transformers/editors/CalculateFieldTransformerEditor/TemplateExpressionOptionsEditor.tsx +++ b/public/app/features/transformers/editors/CalculateFieldTransformerEditor/TemplateExpressionOptionsEditor.tsx @@ -3,16 +3,20 @@ import { useCallback } from 'react'; import { TransformerUIProps, StringFieldConfigSettings, StandardEditorsRegistryItem } from '@grafana/data'; import { CalculateFieldMode, CalculateFieldTransformerOptions } from '@grafana/data/internal'; import { t } from '@grafana/i18n'; +import { getTemplateSrv } from '@grafana/runtime'; import { InlineField, InlineFieldRow } from '@grafana/ui'; import { StringValueEditor } from 'app/core/components/OptionsUI/string'; import { LABEL_WIDTH } from './constants'; +// todo: check why not-scenes throws an error here https://github.com/grafana/grafana/blob/main/public/app/features/templating/template_srv.ts#L297 + export const TemplateExpressionOptionsEditor = ({ input, options, onChange, }: TransformerUIProps) => { + const replaceFn = getTemplateSrv().replace; const onTemplateExpressionChanged = useCallback( (value?: string) => { onChange({ @@ -20,10 +24,11 @@ export const TemplateExpressionOptionsEditor = ({ mode: CalculateFieldMode.TemplateExpression, template: { expression: value ?? '', + replaceFn, }, }); }, - [onChange, options] + [onChange, options, replaceFn] ); const dummyStringSettings: StandardEditorsRegistryItem = {