Remove parsing logic and affix function

This commit is contained in:
Kristina Durivage
2025-07-25 13:31:15 -05:00
parent 44acbb2977
commit de072a25e7
6 changed files with 4 additions and 130 deletions
@@ -584,7 +584,6 @@ Use this transformation to customize the output of a string field. This transfor
- **Kebab case** - Formats all characters in the string in lowercase and uses dashes instead of spaces between words.
- **Trim** - Removes all leading and trailing spaces from the string.
- **Substring** - Returns a substring of the string, using the specified start and end positions.
- **Affix** - Adds a prefix or suffix to the field. Allows pasting of values of other fields using {fieldName} with padding modifiers (see Add field from calculation:Template).
This transformation provides a convenient way to standardize and tailor the presentation of string data for better visualization and analysis.
@@ -15,7 +15,6 @@ import { FieldMatcherID } from '../matchers/ids';
import { ensureColumnsTransformer } from './ensureColumns';
import { DataTransformerID } from './ids';
import { noopTransformer } from './noop';
import { parseTemplateTokens, processTemplateTokens } from './utils';
export enum CalculateFieldMode {
ReduceRow = 'reduceRow',
@@ -258,17 +257,7 @@ export const calculateFieldTransformer: DataTransformerInfo<CalculateFieldTransf
};
});
case CalculateFieldMode.TemplateExpression:
const expression = options.template?.expression ?? '';
const parsedTemplateTokens = parseTemplateTokens(expression);
options.returnType = FieldType.string;
creator = (frame: DataFrame) => {
const outValues: string[] = [];
for (let i = 0; i < frame.length; i++) {
outValues.push(processTemplateTokens(expression, parsedTemplateTokens, frame.fields, i));
}
return outValues;
};
break;
return data;
}
// Nothing configured
@@ -729,6 +718,8 @@ export function getNameFromOptions(options: CalculateFieldTransformerOptions) {
break;
case CalculateFieldMode.Index:
return 'Row';
case CalculateFieldMode.TemplateExpression:
return 'Field';
}
return 'math';
@@ -6,7 +6,6 @@ import { fieldMatchers } from '../matchers';
import { FieldMatcherID } from '../matchers/ids';
import { DataTransformerID } from './ids';
import { parseTemplateTokens, processTemplateTokens } from './utils';
export enum FormatStringOutput {
UpperCase = 'Upper Case',
@@ -19,7 +18,6 @@ export enum FormatStringOutput {
KebabCase = 'Kebab Case',
Trim = 'Trim',
Substring = 'Substring',
Affix = 'Affix',
}
export interface FormatStringTransformerOptions {
@@ -64,16 +62,6 @@ export const getFormatStringFunction = (options: FormatStringTransformerOptions)
return value.trim();
case FormatStringOutput.Substring:
return value.substring(options.substringStart, options.substringEnd);
case FormatStringOutput.Affix:
const prefix = { value: options.stringPrefix ?? '' };
const suffix = { value: options.stringSuffix ?? '' };
[prefix, suffix].forEach((affix) => {
const parsedTemplateTokens = parseTemplateTokens(affix.value);
affix.value = processTemplateTokens(affix.value, parsedTemplateTokens, allFields, index);
});
return prefix.value + value + suffix.value;
}
});
};
@@ -1,5 +1,5 @@
import { BootData } from '../../types/config';
import { DataFrame, Field } from '../../types/dataFrame';
import { DataFrame } from '../../types/dataFrame';
declare global {
interface Window {
@@ -22,57 +22,3 @@ export function findMaxFields(data: DataFrame[]) {
return maxFields;
}
export interface TemplateToken {
token: string;
fieldName: string;
fillChar?: string;
alignment?: string;
width: number;
}
/**
* Extract all template tokens from a string along with any padding modifiers.
*/
export function parseTemplateTokens(templateString: string): TemplateToken[] {
const matchExpr = /{(?<fieldName>[\w\d\._-]+)(?::(?<fillChar>.?(?=[<>^]))?(?<alignment>[<>^])?(?<width>\d+))?}/g;
return [...templateString.matchAll(matchExpr)].map((match) => ({
token: match[0],
fieldName: match.groups!.fieldName,
fillChar: match.groups!.fillChar || ' ',
alignment: match.groups!.alignment || '<',
width: parseInt(match.groups!.width, 10),
}));
}
/**
* Process a template string based on the extracted tokens.
*/
export function processTemplateTokens(
templateString: string,
templateTokens: TemplateToken[],
allFields: Field[],
index: number
) {
let resultString = templateString;
templateTokens.forEach((templateToken) => {
const { token, fieldName, fillChar, alignment, width } = templateToken;
const matchingField = allFields.find((field) => field.name === fieldName);
if (!matchingField) {
return;
}
let replacementValue = matchingField.values[index]?.toString() ?? '';
if (alignment === '<') {
replacementValue = replacementValue.padEnd(width, fillChar || ' ');
} else if (alignment === '>') {
replacementValue = replacementValue.padStart(width, fillChar || ' ');
} else if (alignment === '^') {
const padding = Math.floor(Math.max(0, width - replacementValue.length) / 2);
replacementValue = replacementValue
.padStart(replacementValue.length + padding, fillChar || ' ')
.padEnd(Number(width), fillChar || ' ');
}
resultString = resultString.replaceAll(token, replacementValue);
});
return resultString;
}
@@ -521,7 +521,6 @@ Use this transformation to customize the output of a string field. This transfor
- **Kebab case** - Formats all characters in the string in lowercase and uses dashes instead of spaces between words.
- **Trim** - Removes all leading and trailing spaces from the string.
- **Substring** - Returns a substring of the string, using the specified start and end positions.
- **Affix** - Adds a prefix or suffix to the field. Allows pasting of values of other fields using {fieldName} with padding modifiers (see Add field from calculation:Template).
This transformation provides a convenient way to standardize and tailor the presentation of string data for better visualization and analysis.`;
},
@@ -11,14 +11,12 @@ import {
StandardEditorsRegistryItem,
FieldNamePickerConfigSettings,
TransformerCategory,
StringFieldConfigSettings,
} from '@grafana/data';
import { FormatStringOutput, FormatStringTransformerOptions } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { Select, InlineFieldRow, InlineField } from '@grafana/ui';
import { FieldNamePicker } from '@grafana/ui/internal';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { StringValueEditor } from 'app/core/components/OptionsUI/string';
import darkImage from '../images/dark/formatString.svg';
import lightImage from '../images/light/formatString.svg';
@@ -88,32 +86,8 @@ function FormatStringTransfomerEditor({
[onChange, options]
);
const onPrefixChange = useCallback(
(value?: string) => {
onChange({
...options,
stringPrefix: value ?? '',
});
},
[onChange, options]
);
const onSuffixChange = useCallback(
(value?: string) => {
onChange({
...options,
stringSuffix: value ?? '',
});
},
[onChange, options]
);
const ops = Object.values(FormatStringOutput).map((value) => ({ label: value, value }));
const dummyStringSettings = {
settings: {},
} as StandardEditorsRegistryItem<string, StringFieldConfigSettings>;
return (
<>
<InlineFieldRow>
@@ -144,29 +118,6 @@ function FormatStringTransfomerEditor({
</InlineField>
</InlineFieldRow>
)}
{options.outputFormat === FormatStringOutput.Affix && (
<InlineFieldRow>
<InlineField label={t('transformers.format-string-transfomer-editor.label-prefix', 'Prefix')} labelWidth={15}>
<StringValueEditor
context={{ data: input }}
value={options.stringPrefix ?? ''}
onChange={onPrefixChange}
item={dummyStringSettings}
preserveWhitespace={true}
/>
</InlineField>
<InlineField label={t('transformers.format-string-transfomer-editor.label-suffix', 'Suffix')} labelWidth={15}>
<StringValueEditor
context={{ data: input }}
value={options.stringSuffix ?? ''}
onChange={onSuffixChange}
item={dummyStringSettings}
preserveWhitespace={true}
/>
</InlineField>
</InlineFieldRow>
)}
</>
);
}