Internationalisation: Mark up transformations (#107910)

* CalculateFieldTransformerEditor

* more CalculateFieldTransformer

* ConcatenateTransformerEditor

* ConfigFromQueryTransformerEditor

* mark up other transformations

* few things spotted manually
This commit is contained in:
Ashley Harrison
2025-07-11 11:13:35 +01:00
committed by GitHub
parent 0a0d926531
commit 66b79fb221
54 changed files with 1145 additions and 607 deletions
-4
View File
@@ -2785,10 +2785,6 @@ exports[`better eslint`] = {
"public/app/features/transformers/editors/CalculateFieldTransformerEditor/WindowOptionsEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/transformers/editors/CalculateFieldTransformerEditor/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`CalculateFieldTransformerEditor\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`calculateFieldTransformRegistryItem\`)", "1"]
],
"public/app/features/transformers/editors/ConvertFieldTypeTransformerEditor.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
-2
View File
@@ -14,8 +14,6 @@ import (
v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
)
var ()
var appManifestData = app.ManifestData{
AppName: "iam",
Group: "iam.grafana.app",
@@ -19,7 +19,7 @@ import { MultiValueVariable, sceneGraph, SceneGridRow, VizPanel } from '@grafana
import { Dashboard, LoadingState, Panel, RowPanel, VariableRefresh } from '@grafana/schema';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getTimeRange } from 'app/features/dashboard/utils/timeRange';
import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor';
import { getReduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor';
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/constants';
import { DashboardDataDTO } from 'app/types/dashboard';
@@ -46,7 +46,7 @@ import {
trimDashboardForSnapshot,
} from './transformSceneToSaveModel';
standardTransformersRegistry.setInit(() => [reduceTransformRegistryItem]);
standardTransformersRegistry.setInit(() => [getReduceTransformRegistryItem()]);
setPluginImportUtils({
importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})),
getPanelPluginFromCache: (id: string) => undefined,
@@ -3,7 +3,6 @@ import { FormEventHandler, KeyboardEventHandler, ReactNode, useCallback } from '
import {
DataFrame,
DataTransformerID,
TransformerRegistryItem,
TransformationApplicabilityLevels,
GrafanaTheme2,
@@ -15,17 +14,11 @@ import { Trans, t } from '@grafana/i18n';
import { Badge, Card, Drawer, FilterPill, IconButton, Input, Switch, useStyles2 } from '@grafana/ui';
import config from 'app/core/config';
import { PluginStateInfo } from 'app/features/plugins/components/PluginStateInfo';
import { categoriesLabels } from 'app/features/transformers/utils';
import { getCategoriesLabels } from 'app/features/transformers/utils';
import { FilterCategory } from './TransformationsEditor';
const viewAllLabel = 'View all';
const VIEW_ALL_VALUE = 'viewAll';
const filterCategoriesLabels: Array<[FilterCategory, string]> = [
[VIEW_ALL_VALUE, viewAllLabel],
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
...(Object.entries(categoriesLabels) as Array<[FilterCategory, string]>),
];
interface TransformationPickerNgProps {
onTransformationAdd: (selectedItem: SelectableValue<string>) => void;
@@ -60,6 +53,12 @@ export function TransformationPickerNg(props: TransformationPickerNgProps) {
onSelectedFilterChange,
} = props;
const filterCategoriesLabels: Array<[FilterCategory, string]> = [
[VIEW_ALL_VALUE, t('dashboard.transformation-picker-ng.view-all', 'View all')],
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
...(Object.entries(getCategoriesLabels()) as Array<[FilterCategory, string]>),
];
// Use a callback ref to call "click" on the search input
// This will focus it when it's opened
const searchInputRef = useCallback((input: HTMLInputElement) => {
@@ -218,18 +217,13 @@ function TransformationsGrid({ showIllustrations, transformations, onClick, data
{transform.tags && transform.tags.size > 0 && (
<div className={styles.tagsWrapper}>
{Array.from(transform.tags).map((tag) => (
<Badge
color="darkgrey"
icon="tag-alt"
key={tag}
text={t('transformers.tag', '{{ tag }}', { tag })}
/>
<Badge color="darkgrey" icon="tag-alt" key={tag} text={tag} />
))}
</div>
)}
</Card.Heading>
<Card.Description className={styles.description}>
<span>{getTransformationsRedesignDescriptions(transform.id)}</span>
<span>{standardTransformersRegistry.getIfExists(transform.id)?.description}</span>
{showIllustrations && (
<span>
<img className={styles.image} src={getImagePath(transform.id, !isApplicable)} alt={transform.name} />
@@ -319,28 +313,3 @@ const getImagePath = (id: string, disabled: boolean) => {
const folder = config.theme2.isDark ? 'dark' : 'light';
return `public/build/img/transformations/${folder}/${id}.svg`;
};
const TransformationDescriptionOverrides: { [key: string]: string } = {
[DataTransformerID.concatenate]: 'Combine all fields into a single frame.',
[DataTransformerID.configFromData]: 'Set unit, min, max and more.',
[DataTransformerID.fieldLookup]: 'Use a field value to lookup countries, states, or airports.',
[DataTransformerID.filterFieldsByName]: 'Remove parts of the query results using a regex pattern.',
[DataTransformerID.filterByRefId]: 'Remove rows from the data based on origin query',
[DataTransformerID.filterByValue]: 'Remove rows from the query results using user-defined filters.',
[DataTransformerID.groupBy]: 'Group data by a field value and create aggregate data.',
[DataTransformerID.groupingToMatrix]: 'Summarize and reorganize data based on three fields.',
[DataTransformerID.joinByField]: 'Combine rows from 2+ tables, based on a related field.',
[DataTransformerID.labelsToFields]: 'Group series by time and return labels or tags as fields.',
[DataTransformerID.merge]: 'Merge multiple series. Values will be combined into one row.',
[DataTransformerID.organize]: 'Re-order, hide, or rename fields.',
[DataTransformerID.partitionByValues]: 'Split a one-frame dataset into multiple series.',
[DataTransformerID.prepareTimeSeries]: 'Stretch data frames from the wide format into the long format.',
[DataTransformerID.reduce]: 'Reduce all rows or data points to a single value (ex. max, mean).',
[DataTransformerID.renameByRegex]:
'Rename parts of the query results using a regular expression and replacement pattern.',
[DataTransformerID.seriesToRows]: 'Merge multiple series. Return time, metric and values as a row.',
};
const getTransformationsRedesignDescriptions = (id: string): string => {
return TransformationDescriptionOverrides[id] || standardTransformersRegistry.getIfExists(id)?.description || '';
};
@@ -148,16 +148,19 @@ export const FilterByValueTransformerEditor = (props: TransformerUIProps<FilterB
);
};
export const filterByValueTransformRegistryItem: TransformerRegistryItem<FilterByValueTransformerOptions> = {
id: DataTransformerID.filterByValue,
editor: FilterByValueTransformerEditor,
transformation: standardTransformers.filterByValueTransformer,
name: standardTransformers.filterByValueTransformer.name,
description:
'Removes rows of the query results using user-defined filters. This is useful if you can not filter your data in the data source.',
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.filterByValue).helperDocs,
};
export const getFilterByValueTransformRegistryItem: () => TransformerRegistryItem<FilterByValueTransformerOptions> =
() => ({
id: DataTransformerID.filterByValue,
editor: FilterByValueTransformerEditor,
transformation: standardTransformers.filterByValueTransformer,
name: t('transformers.filter-by-value-transformer-editor.name.filter-data-by-values', 'Filter data by values'),
description: t(
'transformers.filter-by-value-transformer-editor.description.remove-rows-query-results-user-defined-filters',
'Remove rows from the query results using user-defined filters.'
),
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.filterByValue).helperDocs,
});
const useFieldsInfo = (data: DataFrame[]): DataFrameFieldsInfo => {
return useMemo(() => {
@@ -13,7 +13,7 @@ import { getTransformationContent } from '../docs/getTransformationContent';
import { getDefaultOptions, getTransformerOptionPane } from '../spatial/optionsHelper';
import { addHeatmapCalculationOptions } from './editor/helper';
import { HeatmapTransformerOptions, heatmapTransformer } from './heatmap';
import { HeatmapTransformerOptions, getHeatmapTransformer } from './heatmap';
// Nothing defined in state
const supplier = (
@@ -42,13 +42,16 @@ export const HeatmapTransformerEditor = (props: TransformerUIProps<HeatmapTransf
);
};
export const heatmapTransformRegistryItem: TransformerRegistryItem<HeatmapTransformerOptions> = {
id: heatmapTransformer.id,
editor: HeatmapTransformerEditor,
transformation: heatmapTransformer,
name: heatmapTransformer.name,
description: heatmapTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.CreateNewVisualization]),
help: getTransformationContent(heatmapTransformer.id).helperDocs,
export const getHeatmapTransformRegistryItem: () => TransformerRegistryItem<HeatmapTransformerOptions> = () => {
const heatmapTransformer = getHeatmapTransformer();
return {
id: heatmapTransformer.id,
editor: HeatmapTransformerEditor,
transformation: heatmapTransformer,
name: heatmapTransformer.name,
description: heatmapTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.CreateNewVisualization]),
help: getTransformationContent(heatmapTransformer.id).helperDocs,
};
};
@@ -16,6 +16,7 @@ import {
TimeRange,
} from '@grafana/data';
import { isLikelyAscendingVector } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import {
ScaleDistribution,
HeatmapCellLayout,
@@ -30,10 +31,13 @@ export interface HeatmapTransformerOptions extends HeatmapCalculationOptions {
keepOriginalData?: boolean;
}
export const heatmapTransformer: SynchronousDataTransformerInfo<HeatmapTransformerOptions> = {
export const getHeatmapTransformer: () => SynchronousDataTransformerInfo<HeatmapTransformerOptions> = () => ({
id: DataTransformerID.heatmap,
name: 'Create heatmap',
description: 'Generate heatmap data from source data.',
name: t('transformers.get-heatmap-transformer.name.create-heatmap', 'Create heatmap'),
description: t(
'transformers.get-heatmap-transformer.description.generate-heatmap-data-from-source',
'Generate heatmap data from source data.'
),
defaultOptions: {},
isApplicable: (data) => {
const { xField, yField, xs, ys } = findHeatmapFields(data);
@@ -51,7 +55,7 @@ export const heatmapTransformer: SynchronousDataTransformerInfo<HeatmapTransform
isApplicableDescription:
'The Heatmap transformation requires fields with Heatmap compatible data. No fields with Heatmap data could be found.',
operator: (options, ctx) => (source) =>
source.pipe(map((data) => heatmapTransformer.transformer(options, ctx)(data))),
source.pipe(map((data) => getHeatmapTransformer().transformer(options, ctx)(data))),
transformer: (options: HeatmapTransformerOptions) => {
return (data: DataFrame[]) => {
@@ -62,7 +66,7 @@ export const heatmapTransformer: SynchronousDataTransformerInfo<HeatmapTransform
return [v];
};
},
};
});
function parseNumeric(v?: string | null) {
return v === '+Inf' ? Infinity : v === '-Inf' ? -Infinity : +(v ?? 0);
@@ -15,7 +15,7 @@ import { fieldMatchersUI, InlineField, InlineFieldRow, Select, useStyles2 } from
import { getTransformationContent } from '../docs/getTransformationContent';
import { FieldToConfigMappingEditor } from '../fieldToConfigMapping/FieldToConfigMappingEditor';
import { configFromDataTransformer, ConfigFromQueryTransformOptions } from './configFromQuery';
import { getConfigFromDataTransformer, ConfigFromQueryTransformOptions } from './configFromQuery';
export interface Props extends TransformerUIProps<ConfigFromQueryTransformOptions> {}
@@ -98,16 +98,20 @@ export function ConfigFromQueryTransformerEditor({ input, onChange, options }: P
);
}
export const configFromQueryTransformRegistryItem: TransformerRegistryItem<ConfigFromQueryTransformOptions> = {
id: configFromDataTransformer.id,
editor: ConfigFromQueryTransformerEditor,
transformation: configFromDataTransformer,
name: configFromDataTransformer.name,
description: configFromDataTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(configFromDataTransformer.id).helperDocs,
};
export const getConfigFromQueryTransformRegistryItem: () => TransformerRegistryItem<ConfigFromQueryTransformOptions> =
() => {
const configFromDataTransformer = getConfigFromDataTransformer();
return {
id: configFromDataTransformer.id,
editor: ConfigFromQueryTransformerEditor,
transformation: configFromDataTransformer,
name: configFromDataTransformer.name,
description: configFromDataTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(configFromDataTransformer.id).helperDocs,
};
};
const getStyles = (theme: GrafanaTheme2) => ({
matcherOptions: css({
@@ -10,6 +10,7 @@ import {
MatcherConfig,
reduceField,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import {
evaluateFieldMappings,
@@ -89,10 +90,13 @@ export function extractConfigFromQuery(options: ConfigFromQueryTransformOptions,
return output;
}
export const configFromDataTransformer: DataTransformerInfo<ConfigFromQueryTransformOptions> = {
export const getConfigFromDataTransformer: () => DataTransformerInfo<ConfigFromQueryTransformOptions> = () => ({
id: DataTransformerID.configFromData,
name: 'Config from query results',
description: 'Set unit, min, max and more from data.',
name: t('transformers.get-config-from-data-transformer.name.config-from-query-results', 'Config from query results'),
description: t(
'transformers.get-config-from-data-transformer.description.set-unit-min-max-and-more',
'Set unit, min, max and more.'
),
defaultOptions: {
configRefId: 'config',
mappings: [],
@@ -103,4 +107,4 @@ export const configFromDataTransformer: DataTransformerInfo<ConfigFromQueryTrans
* be applied, just return the input series
*/
operator: (options) => (source) => source.pipe(map((data) => extractConfigFromQuery(options, data))),
};
});
@@ -42,20 +42,6 @@ interface CalculateFieldTransformerEditorState {
selected: string[];
}
const calculationModes = [
{ value: CalculateFieldMode.BinaryOperation, label: 'Binary operation' },
{ value: CalculateFieldMode.UnaryOperation, label: 'Unary operation' },
{ value: CalculateFieldMode.ReduceRow, label: 'Reduce row' },
{ value: CalculateFieldMode.Index, label: 'Row index' },
];
if (cfg.featureToggles.addFieldFromCalculationStatFunctions) {
calculationModes.push(
{ value: CalculateFieldMode.CumulativeFunctions, label: 'Cumulative functions' },
{ value: CalculateFieldMode.WindowFunctions, label: 'Window functions' }
);
}
const okTypes = new Set<FieldType>([FieldType.time, FieldType.number, FieldType.string, FieldType.boolean]);
export const CalculateFieldTransformerEditor = (props: CalculateFieldTransformerEditorProps) => {
@@ -63,6 +49,44 @@ export const CalculateFieldTransformerEditor = (props: CalculateFieldTransformer
const configuredOptions = options?.reduce?.include;
const [state, setState] = useState<CalculateFieldTransformerEditorState>({ names: [], selected: [] });
const calculationModes = [
{
value: CalculateFieldMode.BinaryOperation,
label: t(
'transformers.calculate-field-transformer-editor.calculation-modes.label.binary-operation',
'Binary operation'
),
},
{
value: CalculateFieldMode.UnaryOperation,
label: t(
'transformers.calculate-field-transformer-editor.calculation-modes.label.unary-operation',
'Unary operation'
),
},
{
value: CalculateFieldMode.ReduceRow,
label: t('transformers.calculate-field-transformer-editor.calculation-modes.label.reduce-row', 'Reduce row'),
},
{
value: CalculateFieldMode.Index,
label: t('transformers.calculate-field-transformer-editor.calculation-modes.label.row-index', 'Row index'),
},
];
if (cfg.featureToggles.addFieldFromCalculationStatFunctions) {
calculationModes.push(
{
value: CalculateFieldMode.CumulativeFunctions,
label: t('transformers.calculate-field-transformer-editor.label.cumulative-functions', 'Cumulative functions'),
},
{
value: CalculateFieldMode.WindowFunctions,
label: t('transformers.calculate-field-transformer-editor.label.window-functions', 'Window functions'),
}
);
}
useEffect(() => {
const ctx = { interpolate: (v: string) => v };
const subscription = of(input)
@@ -240,12 +264,19 @@ export const CalculateFieldTransformerEditor = (props: CalculateFieldTransformer
);
};
export const calculateFieldTransformRegistryItem: TransformerRegistryItem<CalculateFieldTransformerOptions> = {
id: DataTransformerID.calculateField,
editor: CalculateFieldTransformerEditor,
transformation: standardTransformers.calculateFieldTransformer,
name: standardTransformers.calculateFieldTransformer.name,
description: 'Use the row values to calculate a new field.',
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(DataTransformerID.calculateField).helperDocs,
};
export const getCalculateFieldTransformRegistryItem: () => TransformerRegistryItem<CalculateFieldTransformerOptions> =
() => ({
id: DataTransformerID.calculateField,
editor: CalculateFieldTransformerEditor,
transformation: standardTransformers.calculateFieldTransformer,
name: t(
'transformers.get-calculate-field-transform-registry-item.name.add-field-from-calculation',
'Add field from calculation'
),
description: t(
'transformers.get-calculate-field-transform-registry-item.description.values-calculate-field',
'Use the row values to calculate a new field.'
),
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(DataTransformerID.calculateField).helperDocs,
});
@@ -1,6 +0,0 @@
import {
CalculateFieldTransformerEditor,
calculateFieldTransformRegistryItem,
} from './CalculateFieldTransformerEditor';
export { CalculateFieldTransformerEditor, calculateFieldTransformRegistryItem };
@@ -16,12 +16,6 @@ import { getTransformationContent } from '../docs/getTransformationContent';
interface ConcatenateTransformerEditorProps extends TransformerUIProps<ConcatenateTransformerOptions> {}
const nameModes: Array<SelectableValue<ConcatenateFrameNameMode>> = [
{ value: ConcatenateFrameNameMode.FieldName, label: 'Copy frame name to field name' },
{ value: ConcatenateFrameNameMode.Label, label: 'Add a label with the frame name' },
{ value: ConcatenateFrameNameMode.Drop, label: 'Ignore the frame name' },
];
export class ConcatenateTransformerEditor extends PureComponent<ConcatenateTransformerEditorProps> {
constructor(props: ConcatenateTransformerEditorProps) {
super(props);
@@ -50,6 +44,29 @@ export class ConcatenateTransformerEditor extends PureComponent<ConcatenateTrans
render() {
const { options } = this.props;
const nameModes: Array<SelectableValue<ConcatenateFrameNameMode>> = [
{
value: ConcatenateFrameNameMode.FieldName,
label: t(
'transformers.concatenate-transformer-editor.name-modes.label.copy-frame-name-to-field',
'Copy frame name to field name'
),
},
{
value: ConcatenateFrameNameMode.Label,
label: t(
'transformers.concatenate-transformer-editor.name-modes.label.label-frame',
'Add a label with the frame name'
),
},
{
value: ConcatenateFrameNameMode.Drop,
label: t(
'transformers.concatenate-transformer-editor.name-modes.label.ignore-the-frame-name',
'Ignore the frame name'
),
},
];
const frameNameMode = options.frameNameMode ?? ConcatenateFrameNameMode.FieldName;
@@ -82,14 +99,17 @@ export class ConcatenateTransformerEditor extends PureComponent<ConcatenateTrans
}
}
export const concatenateTransformRegistryItem: TransformerRegistryItem<ConcatenateTransformerOptions> = {
id: DataTransformerID.concatenate,
editor: ConcatenateTransformerEditor,
transformation: standardTransformers.concatenateTransformer,
name: standardTransformers.concatenateTransformer.name,
description:
'Combine all fields into a single frame. Values will be appended with undefined values if not the same length.',
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(DataTransformerID.concatenate).helperDocs,
tags: new Set(['Combine']),
};
export const getConcatenateTransformRegistryItem: () => TransformerRegistryItem<ConcatenateTransformerOptions> =
() => ({
id: DataTransformerID.concatenate,
editor: ConcatenateTransformerEditor,
transformation: standardTransformers.concatenateTransformer,
name: t('transformers.editors.concatenate-transformer-editor.name.concatenate-fields', 'Concatenate fields'),
description: t(
'transformers.editors.concatenate-transformer-editor.description.combine-all-fields',
'Combine all fields into a single frame.'
),
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(DataTransformerID.concatenate).helperDocs,
tags: new Set([t('transformers.editors.concatenate-transformer-editor.tags.combine', 'Combine')]),
});
@@ -267,13 +267,17 @@ export const ConvertFieldTypeTransformerEditor = ({
);
};
export const convertFieldTypeTransformRegistryItem: TransformerRegistryItem<ConvertFieldTypeTransformerOptions> = {
id: DataTransformerID.convertFieldType,
editor: ConvertFieldTypeTransformerEditor,
transformation: standardTransformers.convertFieldTypeTransformer,
name: standardTransformers.convertFieldTypeTransformer.name,
description: standardTransformers.convertFieldTypeTransformer.description,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.convertFieldType).helperDocs,
tags: new Set(['Format field']),
};
export const getConvertFieldTypeTransformRegistryItem: () => TransformerRegistryItem<ConvertFieldTypeTransformerOptions> =
() => ({
id: DataTransformerID.convertFieldType,
editor: ConvertFieldTypeTransformerEditor,
transformation: standardTransformers.convertFieldTypeTransformer,
name: t('transformers.convert-field-type-transformer-editor.name.convert-field-type', 'Convert field type'),
description: t(
'transformers.convert-field-type-transformer-editor.description.convert-to-specified-field-type',
'Convert a field to a specified field type.'
),
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.convertFieldType).helperDocs,
tags: new Set([t('transformers.convert-field-type-transformer-editor.tags.format-field', 'Format field')]),
});
@@ -253,12 +253,16 @@ export class FilterByNameTransformerEditor extends React.PureComponent<
}
}
export const filterFieldsByNameTransformRegistryItem: TransformerRegistryItem<FilterFieldsByNameTransformerOptions> = {
id: DataTransformerID.filterFieldsByName,
editor: FilterByNameTransformerEditor,
transformation: standardTransformers.filterFieldsByNameTransformer,
name: standardTransformers.filterFieldsByNameTransformer.name,
description: 'Removes part of the query results using a regex pattern. The pattern can be inclusive or exclusive.',
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.filterFieldsByName).helperDocs,
};
export const getFilterFieldsByNameTransformRegistryItem: () => TransformerRegistryItem<FilterFieldsByNameTransformerOptions> =
() => ({
id: DataTransformerID.filterFieldsByName,
editor: FilterByNameTransformerEditor,
transformation: standardTransformers.filterFieldsByNameTransformer,
name: t('transformers.filter-by-name-transformer-editor.name.filter-fields-by-name', 'Filter fields by name'),
description: t(
'transformers.filter-by-name-transformer-editor.description.remove-part-query-results-regex-pattern',
'Remove parts of the query results using a regex pattern.'
),
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.filterFieldsByName).helperDocs,
});
@@ -7,6 +7,7 @@ import {
FrameMatcherID,
} from '@grafana/data';
import { FilterFramesByRefIdTransformerOptions } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { FrameMultiSelectionEditor } from 'app/plugins/panel/geomap/editor/FrameSelectionEditor';
import { getTransformationContent } from '../docs/getTransformationContent';
@@ -29,14 +30,16 @@ export const FilterByRefIdTransformerEditor = (props: TransformerUIProps<FilterF
);
};
export const filterFramesByRefIdTransformRegistryItem: TransformerRegistryItem<FilterFramesByRefIdTransformerOptions> =
{
export const getFilterFramesByRefIdTransformRegistryItem: () => TransformerRegistryItem<FilterFramesByRefIdTransformerOptions> =
() => ({
id: DataTransformerID.filterByRefId,
editor: FilterByRefIdTransformerEditor,
transformation: standardTransformers.filterFramesByRefIdTransformer,
name: standardTransformers.filterFramesByRefIdTransformer.name,
description:
'Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel.',
name: t('transformers.filter-by-ref-id-transformer-editor.name.filter-data-by-query', 'Filter data by query'),
description: t(
'transformers.filter-by-ref-id-transformer-editor.description.filter-data-by-query-useful-sharing-results',
'Remove rows from the data based on origin query'
),
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.filterByRefId).helperDocs,
};
});
@@ -119,12 +119,16 @@ function FormatStringTransfomerEditor({
);
}
export const formatStringTransformerRegistryItem: TransformerRegistryItem<FormatStringTransformerOptions> = {
id: DataTransformerID.formatString,
editor: FormatStringTransfomerEditor,
transformation: standardTransformers.formatStringTransformer,
name: standardTransformers.formatStringTransformer.name,
state: PluginState.beta,
description: standardTransformers.formatStringTransformer.description,
categories: new Set([TransformerCategory.Reformat]),
};
export const getFormatStringTransformerRegistryItem: () => TransformerRegistryItem<FormatStringTransformerOptions> =
() => ({
id: DataTransformerID.formatString,
editor: FormatStringTransfomerEditor,
transformation: standardTransformers.formatStringTransformer,
name: t('transformers.format-string-transformer-editor.name.format-string', 'Format string'),
state: PluginState.beta,
description: t(
'transformers.format-string-transformer-editor.description.manipulate-string-fields-formatting',
'Manipulate string fields formatting.'
),
categories: new Set([TransformerCategory.Reformat]),
});
@@ -117,12 +117,16 @@ export function FormatTimeTransfomerEditor({
);
}
export const formatTimeTransformerRegistryItem: TransformerRegistryItem<FormatTimeTransformerOptions> = {
id: DataTransformerID.formatTime,
editor: FormatTimeTransfomerEditor,
transformation: standardTransformers.formatTimeTransformer,
name: standardTransformers.formatTimeTransformer.name,
state: PluginState.alpha,
description: standardTransformers.formatTimeTransformer.description,
help: getTransformationContent(DataTransformerID.formatTime).helperDocs,
};
export const getFormatTimeTransformerRegistryItem: () => TransformerRegistryItem<FormatTimeTransformerOptions> =
() => ({
id: DataTransformerID.formatTime,
editor: FormatTimeTransfomerEditor,
transformation: standardTransformers.formatTimeTransformer,
name: t('transformers.format-time-transformer-editor.name.format-time', 'Format time'),
state: PluginState.alpha,
description: t(
'transformers.format-time-transformer-editor.description.set-based-on-time',
'Set the output format of a time field'
),
help: getTransformationContent(DataTransformerID.formatTime).helperDocs,
});
@@ -86,11 +86,6 @@ export const GroupByTransformerEditor = ({
);
};
const options = [
{ label: 'Group by', value: GroupByOperationID.groupBy },
{ label: 'Calculate', value: GroupByOperationID.aggregate },
];
export const GroupByFieldConfiguration = ({ fieldName, config, onConfigChange }: FieldProps) => {
const theme = useTheme2();
@@ -106,6 +101,17 @@ export const GroupByFieldConfiguration = ({ fieldName, config, onConfigChange }:
[config, onConfigChange]
);
const options = [
{
label: t('transformers.group-by-field-configuration.options.label.group-by', 'Group by'),
value: GroupByOperationID.groupBy,
},
{
label: t('transformers.group-by-field-configuration.options.label.calculate', 'Calculate'),
value: GroupByOperationID.aggregate,
},
];
return (
<InlineField className={styles.label} label={fieldName} grow shrink>
<Stack gap={0.5} direction="row">
@@ -153,16 +159,19 @@ const getStyles = (theme: GrafanaTheme2) => {
};
};
export const groupByTransformRegistryItem: TransformerRegistryItem<GroupByTransformerOptions> = {
export const getGroupByTransformRegistryItem: () => TransformerRegistryItem<GroupByTransformerOptions> = () => ({
id: DataTransformerID.groupBy,
editor: GroupByTransformerEditor,
transformation: standardTransformers.groupByTransformer,
name: standardTransformers.groupByTransformer.name,
description: standardTransformers.groupByTransformer.description,
name: t('transformers.group-by-transformer-editor.name.group-by', 'Group by'),
description: t(
'transformers.group-by-transformer-editor.description.group-series-by-field-calculate-stats',
'Group data by a field value and create aggregate data.'
),
categories: new Set([
TransformerCategory.Combine,
TransformerCategory.CalculateNewFields,
TransformerCategory.Reformat,
]),
help: getTransformationContent(DataTransformerID.groupBy).helperDocs,
};
});
@@ -123,11 +123,6 @@ export const GroupToNestedTableTransformerEditor = ({
);
};
const options = [
{ label: 'Group by', value: GroupByOperationID.groupBy },
{ label: 'Calculate', value: GroupByOperationID.aggregate },
];
export const GroupByFieldConfiguration = ({ fieldName, config, onConfigChange }: FieldProps) => {
const theme = useTheme2();
const styles = getStyles(theme);
@@ -141,6 +136,17 @@ export const GroupByFieldConfiguration = ({ fieldName, config, onConfigChange }:
[config, onConfigChange]
);
const options = [
{
label: t('transformers.group-by-field-configuration.options.label.group-by', 'Group by'),
value: GroupByOperationID.groupBy,
},
{
label: t('transformers.group-by-field-configuration.options.label.calculate', 'Calculate'),
value: GroupByOperationID.aggregate,
},
];
return (
<InlineField className={styles.label} label={fieldName} grow shrink>
<Stack gap={0.5} direction="row" wrap={false}>
@@ -187,16 +193,23 @@ const getStyles = (theme: GrafanaTheme2) => {
};
};
export const groupToNestedTableTransformRegistryItem: TransformerRegistryItem<GroupByTransformerOptions> = {
id: DataTransformerID.groupToNestedTable,
editor: GroupToNestedTableTransformerEditor,
transformation: standardTransformers.groupToNestedTable,
name: standardTransformers.groupToNestedTable.name,
description: standardTransformers.groupToNestedTable.description,
categories: new Set([
TransformerCategory.Combine,
TransformerCategory.CalculateNewFields,
TransformerCategory.Reformat,
]),
state: PluginState.beta,
};
export const getGroupToNestedTableTransformRegistryItem: () => TransformerRegistryItem<GroupByTransformerOptions> =
() => ({
id: DataTransformerID.groupToNestedTable,
editor: GroupToNestedTableTransformerEditor,
transformation: standardTransformers.groupToNestedTable,
name: t(
'transformers.group-to-nested-table-transformer-editor.name.group-to-nested-tables',
'Group to nested tables'
),
description: t(
'transformers.group-to-nested-table-transformer-editor.description.group-by-field-value',
'Group data by a field value and create nested tables with the grouped data.'
),
categories: new Set([
TransformerCategory.Combine,
TransformerCategory.CalculateNewFields,
TransformerCategory.Reformat,
]),
state: PluginState.beta,
});
@@ -148,12 +148,16 @@ export const GroupingToMatrixTransformerEditor = ({
);
};
export const groupingToMatrixTransformRegistryItem: TransformerRegistryItem<GroupingToMatrixTransformerOptions> = {
id: DataTransformerID.groupingToMatrix,
editor: GroupingToMatrixTransformerEditor,
transformation: standardTransformers.groupingToMatrixTransformer,
name: standardTransformers.groupingToMatrixTransformer.name,
description: 'Takes a three fields combination and produces a Matrix.',
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.groupingToMatrix).helperDocs,
};
export const getGroupingToMatrixTransformRegistryItem: () => TransformerRegistryItem<GroupingToMatrixTransformerOptions> =
() => ({
id: DataTransformerID.groupingToMatrix,
editor: GroupingToMatrixTransformerEditor,
transformation: standardTransformers.groupingToMatrixTransformer,
name: t('transformers.grouping-to-matrix-transformer-editor.name.grouping-to-matrix', 'Grouping to matrix'),
description: t(
'transformers.grouping-to-matrix-transformer-editor.description.summarize-and-reorganize-data',
'Summarize and reorganize data based on three fields.'
),
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.groupingToMatrix).helperDocs,
});
@@ -136,12 +136,15 @@ export const HistogramTransformerEditor = ({
);
};
export const histogramTransformRegistryItem: TransformerRegistryItem<HistogramTransformerInputs> = {
export const getHistogramTransformRegistryItem: () => TransformerRegistryItem<HistogramTransformerInputs> = () => ({
id: DataTransformerID.histogram,
editor: HistogramTransformerEditor,
transformation: standardTransformers.histogramTransformer,
name: standardTransformers.histogramTransformer.name,
description: standardTransformers.histogramTransformer.description,
name: t('transformers.histogram-transformer-editor.name.histogram', 'Histogram'),
description: t(
'transformers.histogram-transformer-editor.description.calculate-histogram-from-input-data',
'Calculate a histogram from input data.'
),
categories: new Set([TransformerCategory.CreateNewVisualization]),
help: getTransformationContent(DataTransformerID.histogram).helperDocs,
};
});
@@ -16,30 +16,37 @@ import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/internal';
import { getTransformationContent } from '../docs/getTransformationContent';
const modes = [
{
value: JoinMode.outer,
label: 'OUTER (TIME SERIES)',
description:
'Keep all rows from any table with a value. Join on distinct field values. Performant and best used for time series.',
},
{
value: JoinMode.outerTabular,
label: 'OUTER (TABULAR)',
description:
'Join on a field value with duplicated values. Non performant outer join best used for tabular(SQL like) data.',
},
{
value: JoinMode.inner,
label: 'INNER',
description: 'Combine data from two tables whenever there are matching values in a fields common to both tables.',
},
];
export function SeriesToFieldsTransformerEditor({ input, options, onChange }: TransformerUIProps<JoinByFieldOptions>) {
const names = useFieldDisplayNames(input);
const fieldNames = useSelectOptions(names);
const modes = [
{
value: JoinMode.outer,
label: t('transformers.series-to-fields-transformer-editor.modes.label.outer-time-series', 'Outer (time series)'),
description: t(
'transformers.series-to-fields-transformer-editor.modes.description.keep-all-rows',
'Keep all rows from any table with a value. Join on distinct field values. Performant and best used for time series.'
),
},
{
value: JoinMode.outerTabular,
label: t('transformers.series-to-fields-transformer-editor.modes.label.outer-tabular', 'Outer (tabular)'),
description: t(
'transformers.series-to-fields-transformer-editor.modes.description.join-on-a-field',
'Join on a field value with duplicated values. Non performant outer join best used for tabular(SQL like) data.'
),
},
{
value: JoinMode.inner,
label: t('transformers.series-to-fields-transformer-editor.modes.label.inner', 'Inner'),
description: t(
'transformers.series-to-fields-transformer-editor.modes.description.combine-data-from-two-tables',
'Combine data from two tables whenever there are matching values in a fields common to both tables.'
),
},
];
const variables = getTemplateSrv()
.getVariables()
.map((v) => {
@@ -98,13 +105,16 @@ export function SeriesToFieldsTransformerEditor({ input, options, onChange }: Tr
);
}
export const joinByFieldTransformerRegistryItem: TransformerRegistryItem<JoinByFieldOptions> = {
export const getJoinByFieldTransformerRegistryItem: () => TransformerRegistryItem<JoinByFieldOptions> = () => ({
id: DataTransformerID.joinByField,
aliasIds: [DataTransformerID.seriesToColumns],
editor: SeriesToFieldsTransformerEditor,
transformation: standardTransformers.joinByFieldTransformer,
name: standardTransformers.joinByFieldTransformer.name,
description: standardTransformers.joinByFieldTransformer.description,
name: t('transformers.join-by-field-transformer-editor.name.join-by-field', 'Join by field'),
description: t(
'transformers.join-by-field-transformer-editor.description.combine-rows-from-2-tables',
'Combine rows from 2+ tables, based on a related field.'
),
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(DataTransformerID.joinByField).helperDocs,
};
});
@@ -14,11 +14,6 @@ import { InlineField, InlineFieldRow, RadioButtonGroup, Select, FilterPill, Stac
import { getTransformationContent } from '../docs/getTransformationContent';
const modes: Array<SelectableValue<LabelsToFieldsMode>> = [
{ value: LabelsToFieldsMode.Columns, label: 'Columns' },
{ value: LabelsToFieldsMode.Rows, label: 'Rows' },
];
export const LabelsAsFieldsTransformerEditor = ({
input,
options,
@@ -26,6 +21,17 @@ export const LabelsAsFieldsTransformerEditor = ({
}: TransformerUIProps<LabelsToFieldsOptions>) => {
const labelWidth = 20;
const modes: Array<SelectableValue<LabelsToFieldsMode>> = [
{
value: LabelsToFieldsMode.Columns,
label: t('transformers.labels-as-fields-transformer-editor.modes.label.columns', 'Columns'),
},
{
value: LabelsToFieldsMode.Rows,
label: t('transformers.labels-as-fields-transformer-editor.modes.label.rows', 'Rows'),
},
];
const { labelNames, selected } = useMemo(() => {
let labelNames: Array<SelectableValue<string>> = [];
let uniqueLabels: Record<string, boolean> = {};
@@ -133,13 +139,15 @@ export const LabelsAsFieldsTransformerEditor = ({
);
};
export const labelsToFieldsTransformerRegistryItem: TransformerRegistryItem<LabelsToFieldsOptions> = {
export const getLabelsToFieldsTransformerRegistryItem: () => TransformerRegistryItem<LabelsToFieldsOptions> = () => ({
id: DataTransformerID.labelsToFields,
editor: LabelsAsFieldsTransformerEditor,
transformation: standardTransformers.labelsToFieldsTransformer,
name: standardTransformers.labelsToFieldsTransformer.name,
description: `Groups series by time and return labels or tags as fields.
Useful for showing time series with labels in a table where each label key becomes a separate column.`,
name: t('transformers.labels-to-fields-transformer-editor.name.labels-to-fields', 'Labels to fields'),
description: t(
'transformers.labels-to-fields-transformer-editor.description.groups-series-time-return-labels-tags-fields',
'Group series by time and return labels or tags as fields.'
),
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.labelsToFields).helperDocs,
};
});
@@ -45,12 +45,15 @@ export const LimitTransformerEditor = ({ options, onChange }: TransformerUIProps
);
};
export const limitTransformRegistryItem: TransformerRegistryItem<LimitTransformerOptions> = {
export const getLimitTransformRegistryItem: () => TransformerRegistryItem<LimitTransformerOptions> = () => ({
id: DataTransformerID.limit,
editor: LimitTransformerEditor,
transformation: standardTransformers.limitTransformer,
name: standardTransformers.limitTransformer.name,
description: `Limit the number of items displayed.`,
name: t('transformers.limit-transformer-editor.name.limit', 'Limit'),
description: t(
'transformers.limit-transformer-editor.description.limit-number-items-displayed',
'Limit the number of items displayed.'
),
categories: new Set([TransformerCategory.Filter]),
help: getTransformationContent(DataTransformerID.limit).helperDocs,
};
});
@@ -6,7 +6,7 @@ import {
TransformerCategory,
} from '@grafana/data';
import { MergeTransformerOptions } from '@grafana/data/internal';
import { Trans } from '@grafana/i18n';
import { Trans, t } from '@grafana/i18n';
import { FieldValidationMessage } from '@grafana/ui';
import { getTransformationContent } from '../docs/getTransformationContent';
@@ -25,13 +25,15 @@ export const MergeTransformerEditor = ({ input, options, onChange }: Transformer
return null;
};
export const mergeTransformerRegistryItem: TransformerRegistryItem<MergeTransformerOptions> = {
export const getMergeTransformerRegistryItem: () => TransformerRegistryItem<MergeTransformerOptions> = () => ({
id: DataTransformerID.merge,
editor: MergeTransformerEditor,
transformation: standardTransformers.mergeTransformer,
name: standardTransformers.mergeTransformer.name,
description: `Merge many series/tables and return a single table where mergeable values will be combined into the same row.
Useful for showing multiple series, tables or a combination of both visualized in a table.`,
name: t('transformers.merge-transformer-editor.name.merge', 'Merge series/tables'),
description: t(
'transformers.merge-transformer-editor.description.merge-multiple-series',
'Merge multiple series. Values will be combined into one row.'
),
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(DataTransformerID.merge).helperDocs,
};
});
@@ -495,13 +495,16 @@ const orderFieldNamesByIndex = (fieldNames: string[], indexByName: Record<string
return fieldNames.sort(comparer);
};
export const organizeFieldsTransformRegistryItem: TransformerRegistryItem<OrganizeFieldsTransformerOptions> = {
id: DataTransformerID.organize,
editor: OrganizeFieldsTransformerEditor,
transformation: standardTransformers.organizeFieldsTransformer,
name: standardTransformers.organizeFieldsTransformer.name,
description:
"Allows the user to re-order, hide, or rename fields / columns. Useful when data source doesn't allow overrides for visualizing data.",
categories: new Set([TransformerCategory.ReorderAndRename]),
help: getTransformationContent(DataTransformerID.organize).helperDocs,
};
export const getOrganizeFieldsTransformRegistryItem: () => TransformerRegistryItem<OrganizeFieldsTransformerOptions> =
() => ({
id: DataTransformerID.organize,
editor: OrganizeFieldsTransformerEditor,
transformation: standardTransformers.organizeFieldsTransformer,
name: t('transformers.organize-fields-transformer-editor.name.organize-fields', 'Organize fields by name'),
description: t(
'transformers.organize-fields-transformer-editor.description.reorder-hide-or-rename-fields',
'Re-order, hide, or rename fields.'
),
categories: new Set([TransformerCategory.ReorderAndRename]),
help: getTransformationContent(DataTransformerID.organize).helperDocs,
});
@@ -117,12 +117,15 @@ export const ReduceTransformerEditor = ({ options, onChange }: TransformerUIProp
);
};
export const reduceTransformRegistryItem: TransformerRegistryItem<ReduceTransformerOptions> = {
export const getReduceTransformRegistryItem: () => TransformerRegistryItem<ReduceTransformerOptions> = () => ({
id: DataTransformerID.reduce,
editor: ReduceTransformerEditor,
transformation: standardTransformers.reduceTransformer,
name: standardTransformers.reduceTransformer.name,
description: standardTransformers.reduceTransformer.description,
name: t('transformers.reduce-transformer-editor.name.reduce', 'Reduce'),
description: t(
'transformers.reduce-transformer-editor.description.reduce-to-single-value',
'Reduce all rows or data points to a single value (ex. max, mean).'
),
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(DataTransformerID.reduce).helperDocs,
};
});
@@ -120,12 +120,16 @@ export class RenameByRegexTransformerEditor extends React.PureComponent<
}
}
export const renameByRegexTransformRegistryItem: TransformerRegistryItem<RenameByRegexTransformerOptions> = {
id: DataTransformerID.renameByRegex,
editor: RenameByRegexTransformerEditor,
transformation: standardTransformers.renameByRegexTransformer,
name: standardTransformers.renameByRegexTransformer.name,
description: 'Renames part of the query result by using regular expression with placeholders.',
categories: new Set([TransformerCategory.ReorderAndRename]),
help: getTransformationContent(DataTransformerID.renameByRegex).helperDocs,
};
export const getRenameByRegexTransformRegistryItem: () => TransformerRegistryItem<RenameByRegexTransformerOptions> =
() => ({
id: DataTransformerID.renameByRegex,
editor: RenameByRegexTransformerEditor,
transformation: standardTransformers.renameByRegexTransformer,
name: t('transformers.rename-by-regex-transformer.name.rename-fields-by-regex', 'Rename fields by regex'),
description: t(
'transformers.rename-by-regex-transformer.description.rename-parts-using-regex',
'Rename parts of the query results using a regular expression and replacement pattern.'
),
categories: new Set([TransformerCategory.ReorderAndRename]),
help: getTransformationContent(DataTransformerID.renameByRegex).helperDocs,
});
@@ -6,6 +6,7 @@ import {
TransformerCategory,
} from '@grafana/data';
import { SeriesToRowsTransformerOptions } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { getTransformationContent } from '../docs/getTransformationContent';
@@ -17,13 +18,16 @@ export const SeriesToRowsTransformerEditor = ({
return null;
};
export const seriesToRowsTransformerRegistryItem: TransformerRegistryItem<SeriesToRowsTransformerOptions> = {
id: DataTransformerID.seriesToRows,
editor: SeriesToRowsTransformerEditor,
transformation: standardTransformers.seriesToRowsTransformer,
name: standardTransformers.seriesToRowsTransformer.name,
description: `Merge many series and return a single series with time, metric and value as columns.
Useful for showing multiple time series visualized in a table.`,
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.seriesToRows).helperDocs,
};
export const getSeriesToRowsTransformerRegistryItem: () => TransformerRegistryItem<SeriesToRowsTransformerOptions> =
() => ({
id: DataTransformerID.seriesToRows,
editor: SeriesToRowsTransformerEditor,
transformation: standardTransformers.seriesToRowsTransformer,
name: t('transformers.series-to-rows-transformer-editor.name.series-to-rows', 'Series to rows'),
description: t(
'transformers.series-to-rows-transformer-editor.description.merge-multiple-series',
'Merge multiple series. Return time, metric and values as a row.'
),
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.seriesToRows).helperDocs,
});
@@ -64,12 +64,12 @@ export const SortByTransformerEditor = ({ input, options, onChange }: Transforme
);
};
export const sortByTransformRegistryItem: TransformerRegistryItem<SortByTransformerOptions> = {
export const getSortByTransformRegistryItem: () => TransformerRegistryItem<SortByTransformerOptions> = () => ({
id: DataTransformerID.sortBy,
editor: SortByTransformerEditor,
transformation: standardTransformers.sortByTransformer,
name: standardTransformers.sortByTransformer.name,
description: standardTransformers.sortByTransformer.description,
name: t('transformers.sort-by-transformer-editor.name.sort-by', 'Sort by'),
description: t('transformers.sort-by-transformer-editor.description.sort-fields', 'Sort fields in a frame.'),
categories: new Set([TransformerCategory.ReorderAndRename]),
help: getTransformationContent(DataTransformerID.sortBy).helperDocs,
};
});
@@ -43,12 +43,19 @@ export const TransposeTransformerEditor = ({ options, onChange }: TransformerUIP
);
};
export const transposeTransformerRegistryItem: TransformerRegistryItem<TransposeTransformerOptions> = {
export const getTransposeTransformerRegistryItem: () => TransformerRegistryItem<TransposeTransformerOptions> = () => ({
id: DataTransformerID.transpose,
editor: TransposeTransformerEditor,
transformation: standardTransformers.transposeTransformer,
name: standardTransformers.transposeTransformer.name,
description: standardTransformers.transposeTransformer.description,
name: t('transformers.transpose-transformer-editor.name.transpose', 'Transpose'),
description: t(
'transformers.transpose-transformer-editor.description.transpose-data-frame',
'Transpose the data frame.'
),
categories: new Set([TransformerCategory.Reformat]),
tags: new Set(['Pivot', 'Translate', 'Transform']),
};
tags: new Set([
t('transformers.transpose-transformer-editor.tags.pivot', 'Pivot'),
t('transformers.transpose-transformer-editor.tags.translate', 'Translate'),
t('transformers.transpose-transformer-editor.tags.transform', 'Transform'),
]),
});
@@ -180,12 +180,15 @@ export const extractFieldsTransformerEditor = ({
);
};
export const extractFieldsTransformRegistryItem: TransformerRegistryItem<ExtractFieldsOptions> = {
export const getExtractFieldsTransformRegistryItem: () => TransformerRegistryItem<ExtractFieldsOptions> = () => ({
id: DataTransformerID.extractFields,
editor: extractFieldsTransformerEditor,
transformation: extractFieldsTransformer,
name: extractFieldsTransformer.name,
description: `Parse fields from content (JSON, labels, etc).`,
name: t('transformers.extract-fields-transformer-editor.name.extract-fields', 'Extract fields'),
description: t(
'transformers.extract-fields-transformer-editor.description.parse-fields-from-content',
'Parse fields from content (JSON, labels, etc).'
),
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.extractFields).helperDocs,
};
});
@@ -14,7 +14,7 @@ import { Alert, HorizontalGroup, InlineField, InlineFieldRow, Select, ValuePicke
import { getTransformationContent } from '../docs/getTransformationContent';
import { getDistinctLabels } from '../utils';
import { joinByLabelsTransformer, JoinByLabelsTransformOptions } from './joinByLabels';
import { getJoinByLabelsTransformer, JoinByLabelsTransformOptions } from './joinByLabels';
export interface Props extends TransformerUIProps<JoinByLabelsTransformOptions> {}
@@ -108,7 +108,7 @@ export function JoinByLabelsTransformerEditor({ input, options, onChange }: Prop
<InlineFieldRow>
<InlineField
error="required"
error={t('transformers.join-by-labels-transformer-editor.error-required', 'Required')}
invalid={!Boolean(options.value?.length)}
label={t('transformers.join-by-labels-transformer-editor.label-value', 'Value')}
labelWidth={labelWidth}
@@ -178,13 +178,16 @@ export function JoinByLabelsTransformerEditor({ input, options, onChange }: Prop
);
}
export const joinByLabelsTransformRegistryItem: TransformerRegistryItem<JoinByLabelsTransformOptions> = {
id: joinByLabelsTransformer.id,
editor: JoinByLabelsTransformerEditor,
transformation: joinByLabelsTransformer,
name: joinByLabelsTransformer.name,
description: joinByLabelsTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(joinByLabelsTransformer.id).helperDocs,
export const getJoinByLabelsTransformRegistryItem: () => TransformerRegistryItem<JoinByLabelsTransformOptions> = () => {
const joinByLabelsTransformer = getJoinByLabelsTransformer();
return {
id: joinByLabelsTransformer.id,
editor: JoinByLabelsTransformerEditor,
transformation: joinByLabelsTransformer,
name: joinByLabelsTransformer.name,
description: joinByLabelsTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.Combine]),
help: getTransformationContent(joinByLabelsTransformer.id).helperDocs,
};
};
@@ -1,6 +1,7 @@
import { map } from 'rxjs/operators';
import { DataFrame, DataTransformerID, Field, FieldType, SynchronousDataTransformerInfo } from '@grafana/data';
import { t } from '@grafana/i18n';
import { getDistinctLabels } from '../utils';
@@ -9,14 +10,17 @@ export interface JoinByLabelsTransformOptions {
join?: string[];
}
export const joinByLabelsTransformer: SynchronousDataTransformerInfo<JoinByLabelsTransformOptions> = {
export const getJoinByLabelsTransformer: () => SynchronousDataTransformerInfo<JoinByLabelsTransformOptions> = () => ({
id: DataTransformerID.joinByLabels,
name: 'Join by labels',
description: 'Flatten labeled results into a table joined by labels.',
name: t('transformers.get-join-by-labels-transformer.name.join-by-labels', 'Join by labels'),
description: t(
'transformers.get-join-by-labels-transformer.description.flatten-labeled-results-table-joined-labels',
'Flatten labeled results into a table joined by labels.'
),
defaultOptions: {},
operator: (options, ctx) => (source) =>
source.pipe(map((data) => joinByLabelsTransformer.transformer(options, ctx)(data))),
source.pipe(map((data) => getJoinByLabelsTransformer().transformer(options, ctx)(data))),
transformer: (options: JoinByLabelsTransformOptions) => {
return (data: DataFrame[]) => {
@@ -26,7 +30,7 @@ export const joinByLabelsTransformer: SynchronousDataTransformerInfo<JoinByLabel
return [joinByLabels(options, data)];
};
},
};
});
interface JoinValues {
keys: string[];
@@ -87,13 +87,19 @@ export const FieldLookupTransformerEditor = ({ input, options, onChange }: Trans
);
};
export const fieldLookupTransformRegistryItem: TransformerRegistryItem<FieldLookupOptions> = {
export const getFieldLookupTransformRegistryItem: () => TransformerRegistryItem<FieldLookupOptions> = () => ({
id: DataTransformerID.fieldLookup,
editor: FieldLookupTransformerEditor,
transformation: fieldLookupTransformer,
name: fieldLookupTransformer.name,
description: `Use a field value to lookup additional fields from an external source. This currently supports spatial data, but will eventually support more formats.`,
name: t(
'transformers.field-lookup-transformer-editor.name.lookup-fields-from-resource',
'Lookup fields from resource'
),
description: t(
'transformers.field-lookup-transformer-editor.description.lookup-additional-fields-external-source',
'Use a field value to lookup countries, states, or airports.'
),
state: PluginState.alpha,
categories: new Set([TransformerCategory.PerformSpatialOperations]),
help: getTransformationContent(DataTransformerID.fieldLookup).helperDocs,
};
});
@@ -19,7 +19,7 @@ export interface FieldLookupOptions {
export const fieldLookupTransformer: DataTransformerInfo<FieldLookupOptions> = {
id: DataTransformerID.fieldLookup,
name: 'Lookup fields from resource',
description: 'Retrieve matching data based on specified field',
description: 'Use a field value to lookup countries, states, or airports.',
defaultOptions: {},
operator: (options) => (source) => source.pipe(mergeMap((data) => from(doGazetteerXform(data, options)))),
@@ -22,7 +22,7 @@ import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/internal';
import { getTransformationContent } from '../docs/getTransformationContent';
import { partitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues';
import { getPartitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues';
export function PartitionByValuesEditor({
input,
@@ -178,13 +178,17 @@ export function PartitionByValuesEditor({
);
}
export const partitionByValuesTransformRegistryItem: TransformerRegistryItem<PartitionByValuesTransformerOptions> = {
id: DataTransformerID.partitionByValues,
editor: PartitionByValuesEditor,
transformation: partitionByValuesTransformer,
name: partitionByValuesTransformer.name,
description: partitionByValuesTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.partitionByValues).helperDocs,
};
export const getPartitionByValuesTransformRegistryItem: () => TransformerRegistryItem<PartitionByValuesTransformerOptions> =
() => {
const partitionByValuesTransformer = getPartitionByValuesTransformer();
return {
id: DataTransformerID.partitionByValues,
editor: PartitionByValuesEditor,
transformation: partitionByValuesTransformer,
name: partitionByValuesTransformer.name,
description: partitionByValuesTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(DataTransformerID.partitionByValues).helperDocs,
};
};
@@ -1,12 +1,14 @@
import { toDataFrame, FieldType } from '@grafana/data';
import { partitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues';
import { getPartitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues';
const ctx = {
interpolate: (v: string) => v,
};
describe('Partition by values transformer', () => {
const partitionByValuesTransformer = getPartitionByValuesTransformer();
it('should partition by one field', () => {
const source = [
toDataFrame({
@@ -9,6 +9,7 @@ import {
FieldMatcher,
} from '@grafana/data';
import { getMatcherConfig, noopTransformer } from '@grafana/data/internal';
import { t } from '@grafana/i18n';
import { partition } from './partition';
@@ -62,35 +63,39 @@ function buildFieldLabels(names: string[], values: unknown[]) {
return labels;
}
export const partitionByValuesTransformer: SynchronousDataTransformerInfo<PartitionByValuesTransformerOptions> = {
id: DataTransformerID.partitionByValues,
name: 'Partition by values',
description: `Splits a one-frame dataset into multiple series discriminated by unique/enum values in one or more fields.`,
defaultOptions: {
keepFields: false,
},
export const getPartitionByValuesTransformer: () => SynchronousDataTransformerInfo<PartitionByValuesTransformerOptions> =
() => ({
id: DataTransformerID.partitionByValues,
name: t('transformers.get-partition-by-values-transformer.name.partition-by-values', 'Partition by values'),
description: t(
'transformers.get-partition-by-values-transformer.description.split-oneframe-dataset-multiple-series',
'Split a one-frame dataset into multiple series.'
),
defaultOptions: {
keepFields: false,
},
operator: (options, ctx) => (source) =>
source.pipe(map((data) => partitionByValuesTransformer.transformer(options, ctx)(data))),
operator: (options, ctx) => (source) =>
source.pipe(map((data) => getPartitionByValuesTransformer().transformer(options, ctx)(data))),
transformer: (options: PartitionByValuesTransformerOptions, ctx: DataTransformContext) => {
const matcherConfig = getMatcherConfig({ names: options.fields });
transformer: (options: PartitionByValuesTransformerOptions, ctx: DataTransformContext) => {
const matcherConfig = getMatcherConfig({ names: options.fields });
if (!matcherConfig) {
return noopTransformer.transformer({}, ctx);
}
const matcher = getFieldMatcher(matcherConfig);
return (data: DataFrame[]) => {
if (!data.length) {
return data;
if (!matcherConfig) {
return noopTransformer.transformer({}, ctx);
}
// error if > 1 frame?
return partitionByValues(data[0], matcher, options);
};
},
};
const matcher = getFieldMatcher(matcherConfig);
return (data: DataFrame[]) => {
if (!data.length) {
return data;
}
// error if > 1 frame?
return partitionByValues(data[0], matcher, options);
};
},
});
// Split a single frame dataset into multiple frames based on values in a set of fields
export function partitionByValues(
@@ -14,96 +14,110 @@ import { InlineField, InlineFieldRow, Select, useStyles2 } from '@grafana/ui';
import { getTransformationContent } from '../docs/getTransformationContent';
import { prepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries';
const wideInfo = {
label: 'Wide time series',
value: timeSeriesFormat.TimeSeriesWide,
description: 'Creates a single frame joined by time',
info: (
<ul>
<li>
<Trans i18nKey="transformers.wide-info.single-frame">Single frame</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.st-field-is-shared-time">1st field is shared time field</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.time-in-ascending-order">Time in ascending order</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.multiple-value-fields-of-any-type">
Multiple value fields of any type
</Trans>
</li>
</ul>
),
};
const multiInfo = {
label: 'Multi-frame time series',
value: timeSeriesFormat.TimeSeriesMulti,
description: 'Creates a new frame for each time/number pair',
info: (
<ul>
<li>
<Trans i18nKey="transformers.multi-info.multiple-frames">Multiple frames</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.frame-fields-value" values={{ field1: 'time', field2: 'value' }}>
Each frame has two fields: {'{{field1}}'}, {'{{field2}}'}
</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.time-in-ascending-order">Time in ascending order</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.string-values-are-represented-as-labels">
String values are represented as labels
</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.all-values-are-numeric">All values are numeric</Trans>
</li>
</ul>
),
};
const longInfo = {
label: 'Long time series',
value: timeSeriesFormat.TimeSeriesLong,
description: 'Convert each frame to long format',
info: (
<ul>
<li>
<Trans i18nKey="transformers.long-info.single-frame">Single frame</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.st-field-is-time">1st field is time field</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.ascending-order-duplicates">
Time in ascending order, but may have duplicates
</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.string-values-separate">
String values are represented as separate fields rather than as labels
</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.multiple-value-fields-may-exist">Multiple value fields may exist</Trans>
</li>
</ul>
),
};
const formats: Array<SelectableValue<timeSeriesFormat>> = [wideInfo, multiInfo, longInfo];
import { PrepareTimeSeriesOptions, timeSeriesFormat, getPrepareTimeSeriesTransformer } from './prepareTimeSeries';
export function PrepareTimeSeriesEditor(props: TransformerUIProps<PrepareTimeSeriesOptions>): React.ReactElement {
const { options, onChange } = props;
const styles = useStyles2(getStyles);
const wideInfo = {
label: t('transformers.prepare-time-series-editor.wide-info.label.wide-time-series', 'Wide time series'),
value: timeSeriesFormat.TimeSeriesWide,
description: t(
'transformers.prepare-time-series-editor.wide-info.description.creates-single-frame-joined',
'Creates a single frame joined by time'
),
info: (
<ul>
<li>
<Trans i18nKey="transformers.wide-info.single-frame">Single frame</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.st-field-is-shared-time">1st field is shared time field</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.time-in-ascending-order">Time in ascending order</Trans>
</li>
<li>
<Trans i18nKey="transformers.wide-info.multiple-value-fields-of-any-type">
Multiple value fields of any type
</Trans>
</li>
</ul>
),
};
const multiInfo = {
label: t(
'transformers.prepare-time-series-editor.multi-info.label.multiframe-time-series',
'Multi-frame time series'
),
value: timeSeriesFormat.TimeSeriesMulti,
description: t(
'transformers.prepare-time-series-editor.multi-info.description.creates-frame-timenumber',
'Creates a new frame for each time/number pair'
),
info: (
<ul>
<li>
<Trans i18nKey="transformers.multi-info.multiple-frames">Multiple frames</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.frame-fields-value" values={{ field1: 'time', field2: 'value' }}>
Each frame has two fields: {'{{field1}}'}, {'{{field2}}'}
</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.time-in-ascending-order">Time in ascending order</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.string-values-are-represented-as-labels">
String values are represented as labels
</Trans>
</li>
<li>
<Trans i18nKey="transformers.multi-info.all-values-are-numeric">All values are numeric</Trans>
</li>
</ul>
),
};
const longInfo = {
label: t('transformers.prepare-time-series-editor.long-info.label.long-time-series', 'Long time series'),
value: timeSeriesFormat.TimeSeriesLong,
description: t(
'transformers.prepare-time-series-editor.long-info.description.convert-each-frame-to-long-format',
'Convert each frame to long format'
),
info: (
<ul>
<li>
<Trans i18nKey="transformers.long-info.single-frame">Single frame</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.st-field-is-time">1st field is time field</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.ascending-order-duplicates">
Time in ascending order, but may have duplicates
</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.string-values-separate">
String values are represented as separate fields rather than as labels
</Trans>
</li>
<li>
<Trans i18nKey="transformers.long-info.multiple-value-fields-may-exist">
Multiple value fields may exist
</Trans>
</li>
</ul>
),
};
const formats: Array<SelectableValue<timeSeriesFormat>> = [wideInfo, multiInfo, longInfo];
const onSelectFormat = useCallback(
(value: SelectableValue<timeSeriesFormat>) => {
onChange({
@@ -154,12 +168,16 @@ const getStyles = (theme: GrafanaTheme2) => ({
}),
});
export const prepareTimeseriesTransformerRegistryItem: TransformerRegistryItem<PrepareTimeSeriesOptions> = {
id: prepareTimeSeriesTransformer.id,
editor: PrepareTimeSeriesEditor,
transformation: prepareTimeSeriesTransformer,
name: prepareTimeSeriesTransformer.name,
description: prepareTimeSeriesTransformer.description,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(prepareTimeSeriesTransformer.id).helperDocs,
};
export const getPrepareTimeseriesTransformerRegistryItem: () => TransformerRegistryItem<PrepareTimeSeriesOptions> =
() => {
const prepareTimeSeriesTransformer = getPrepareTimeSeriesTransformer();
return {
id: prepareTimeSeriesTransformer.id,
editor: PrepareTimeSeriesEditor,
transformation: prepareTimeSeriesTransformer,
name: prepareTimeSeriesTransformer.name,
description: prepareTimeSeriesTransformer.description,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(prepareTimeSeriesTransformer.id).helperDocs,
};
};
@@ -8,13 +8,15 @@ import {
getFrameDisplayName,
} from '@grafana/data';
import { prepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries';
import { getPrepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries';
const ctx = {
interpolate: (v: string) => v,
};
describe('Prepare time series transformer', () => {
const prepareTimeSeriesTransformer = getPrepareTimeSeriesTransformer();
it('should transform wide to multi', () => {
const source = [
toDataFrame({
@@ -12,6 +12,7 @@ import {
Field,
MutableDataFrame,
} from '@grafana/data';
import { t } from '@grafana/i18n';
import { Labels } from 'app/types/unified-alerting-dto';
import { partitionByValues } from '../partitionByValues/partitionByValues';
@@ -299,14 +300,17 @@ export function longToMultiTimeSeries(frame: DataFrame): DataFrame[] {
});
}
export const prepareTimeSeriesTransformer: SynchronousDataTransformerInfo<PrepareTimeSeriesOptions> = {
export const getPrepareTimeSeriesTransformer: () => SynchronousDataTransformerInfo<PrepareTimeSeriesOptions> = () => ({
id: DataTransformerID.prepareTimeSeries,
name: 'Prepare time series',
description: `Will stretch data frames from the wide format into the long format. This is really helpful to be able to keep backwards compatibility for panels not supporting the new wide format.`,
name: t('transformers.prepare-time-series.name.prepare-time-series', 'Prepare time series'),
description: t(
'transformers.prepare-time-series.description.stretch-data-frames',
'Stretch data frames from the wide format into the long format.'
),
defaultOptions: {},
operator: (options, ctx) => (source) =>
source.pipe(map((data) => prepareTimeSeriesTransformer.transformer(options, ctx)(data))),
source.pipe(map((data) => getPrepareTimeSeriesTransformer().transformer(options, ctx)(data))),
transformer: (options: PrepareTimeSeriesOptions) => {
const format = options?.format ?? timeSeriesFormat.TimeSeriesWide;
@@ -349,4 +353,4 @@ export const prepareTimeSeriesTransformer: SynchronousDataTransformerInfo<Prepar
return [];
};
},
};
});
@@ -8,9 +8,11 @@ import {
toDataFrameDTO,
} from '@grafana/data';
import { ModelType, RegressionTransformer, RegressionTransformerOptions } from './regression';
import { ModelType, getRegressionTransformer, RegressionTransformerOptions } from './regression';
describe('Regression transformation', () => {
const RegressionTransformer = getRegressionTransformer();
it('it should predict a linear regression to exactly fit the data when the data is f(x) = x', () => {
const source = [
toDataFrame({
@@ -35,12 +35,15 @@ export const DEGREES = [
{ label: () => t('transformers.regression-transformer-editor.label.quintic', 'Quintic'), value: 5 },
];
export const RegressionTransformer: SynchronousDataTransformerInfo<RegressionTransformerOptions> = {
export const getRegressionTransformer: () => SynchronousDataTransformerInfo<RegressionTransformerOptions> = () => ({
id: DataTransformerID.regression,
name: 'Regression analysis',
description: 'Create a new data frame containing values predicted by a statistical model.',
name: t('transformers.regression.name.regression-analysis', 'Regression analysis'),
description: t(
'transformers.regression.description.create-new-data-frame',
'Create a new data frame containing values predicted by a statistical model.'
),
operator: (options, ctx) => (source) =>
source.pipe(map((data) => RegressionTransformer.transformer(options, ctx)(data))),
source.pipe(map((data) => getRegressionTransformer().transformer(options, ctx)(data))),
transformer: (options, ctx) => {
return (frames: DataFrame[]) => {
const { predictionCount, modelType, degree } = { ...DEFAULTS, ...options };
@@ -137,4 +140,4 @@ export const RegressionTransformer: SynchronousDataTransformerInfo<RegressionTra
return [...frames, newFrame];
};
},
};
});
@@ -16,7 +16,7 @@ import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
import { getTransformationContent } from '../docs/getTransformationContent';
import { DEFAULTS, DEGREES, ModelType, RegressionTransformer, RegressionTransformerOptions } from './regression';
import { DEFAULTS, DEGREES, ModelType, getRegressionTransformer, RegressionTransformerOptions } from './regression';
const fieldNamePickerSettings = {
editor: FieldNamePicker,
@@ -157,12 +157,15 @@ export const RegressionTransformerEditor = ({
);
};
export const regressionTransformerRegistryItem: TransformerRegistryItem<RegressionTransformerOptions> = {
id: DataTransformerID.regression,
editor: RegressionTransformerEditor,
transformation: RegressionTransformer,
name: RegressionTransformer.name,
description: RegressionTransformer.description,
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(DataTransformerID.regression).helperDocs,
export const getRegressionTransformerRegistryItem: () => TransformerRegistryItem<RegressionTransformerOptions> = () => {
const regressionTransformer = getRegressionTransformer();
return {
id: DataTransformerID.regression,
editor: RegressionTransformerEditor,
transformation: regressionTransformer,
name: regressionTransformer.name,
description: regressionTransformer.description,
categories: new Set([TransformerCategory.CalculateNewFields]),
help: getTransformationContent(DataTransformerID.regression).helperDocs,
};
};
@@ -3,7 +3,7 @@ import { PluginState, TransformerRegistryItem, TransformerUIProps, TransformerCa
import { getTransformationContent } from '../docs/getTransformationContent';
import { FieldToConfigMappingEditor } from '../fieldToConfigMapping/FieldToConfigMappingEditor';
import { rowsToFieldsTransformer, RowToFieldsTransformOptions } from './rowsToFields';
import { getRowsToFieldsTransformer, RowToFieldsTransformOptions } from './rowsToFields';
export interface Props extends TransformerUIProps<RowToFieldsTransformOptions> {}
@@ -24,13 +24,16 @@ export function RowsToFieldsTransformerEditor({ input, options, onChange }: Prop
);
}
export const rowsToFieldsTransformRegistryItem: TransformerRegistryItem<RowToFieldsTransformOptions> = {
id: rowsToFieldsTransformer.id,
editor: RowsToFieldsTransformerEditor,
transformation: rowsToFieldsTransformer,
name: rowsToFieldsTransformer.name,
description: rowsToFieldsTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(rowsToFieldsTransformer.id).helperDocs,
export const getRowsToFieldsTransformRegistryItem: () => TransformerRegistryItem<RowToFieldsTransformOptions> = () => {
const rowsToFieldsTransformer = getRowsToFieldsTransformer();
return {
id: rowsToFieldsTransformer.id,
editor: RowsToFieldsTransformerEditor,
transformation: rowsToFieldsTransformer,
name: rowsToFieldsTransformer.name,
description: rowsToFieldsTransformer.description,
state: PluginState.beta,
categories: new Set([TransformerCategory.Reformat]),
help: getTransformationContent(rowsToFieldsTransformer.id).helperDocs,
};
};
@@ -1,6 +1,7 @@
import { map } from 'rxjs/operators';
import { DataFrame, DataTransformerID, DataTransformerInfo, Field, getFieldDisplayName, Labels } from '@grafana/data';
import { t } from '@grafana/i18n';
import {
EvaluatedMappingResult,
@@ -16,10 +17,13 @@ export interface RowToFieldsTransformOptions {
mappings?: FieldToConfigMapping[];
}
export const rowsToFieldsTransformer: DataTransformerInfo<RowToFieldsTransformOptions> = {
export const getRowsToFieldsTransformer: () => DataTransformerInfo<RowToFieldsTransformOptions> = () => ({
id: DataTransformerID.rowsToFields,
name: 'Rows to fields',
description: 'Convert each row into a field with dynamic config.',
name: t('transformers.get-rows-to-fields-transformer.name.rows-to-fields', 'Rows to fields'),
description: t(
'transformers.get-rows-to-fields-transformer.description.convert-field-dynamic-config',
'Convert each row into a field with dynamic config.'
),
defaultOptions: {},
/**
@@ -32,7 +36,7 @@ export const rowsToFieldsTransformer: DataTransformerInfo<RowToFieldsTransformOp
return data.map((frame) => rowsToFields(options, frame));
})
),
};
});
export function rowsToFields(options: RowToFieldsTransformOptions, data: DataFrame): DataFrame {
const mappingResult = evaluateFieldMappings(data, options.mappings ?? [], true);
@@ -20,7 +20,7 @@ import { getTransformationContent } from '../docs/getTransformationContent';
import { SpatialCalculation, SpatialOperation, SpatialAction, SpatialTransformOptions } from './models.gen';
import { getDefaultOptions, getTransformerOptionPane } from './optionsHelper';
import { isLineBuilderOption, spatialTransformer } from './spatialTransformer';
import { isLineBuilderOption, getSpatialTransformer } from './spatialTransformer';
// Nothing defined in state
const supplier = (
@@ -173,13 +173,16 @@ const getStyles = (theme: GrafanaTheme2) => {
};
};
export const spatialTransformRegistryItem: TransformerRegistryItem<SpatialTransformOptions> = {
id: DataTransformerID.spatial,
editor: SetGeometryTransformerEditor,
transformation: spatialTransformer,
name: spatialTransformer.name,
description: spatialTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.PerformSpatialOperations]),
help: getTransformationContent(DataTransformerID.spatial).helperDocs,
export const getSpatialTransformRegistryItem: () => TransformerRegistryItem<SpatialTransformOptions> = () => {
const spatialTransformer = getSpatialTransformer();
return {
id: DataTransformerID.spatial,
editor: SetGeometryTransformerEditor,
transformation: spatialTransformer,
name: spatialTransformer.name,
description: spatialTransformer.description,
state: PluginState.alpha,
categories: new Set([TransformerCategory.PerformSpatialOperations]),
help: getTransformationContent(DataTransformerID.spatial).helperDocs,
};
};
@@ -1,20 +1,24 @@
import { mergeMap, from } from 'rxjs';
import { DataFrame, DataTransformerID, DataTransformerInfo, FieldType } from '@grafana/data';
import { t } from '@grafana/i18n';
import { createGeometryCollection, createLineBetween } from 'app/features/geo/format/utils';
import { getGeometryField, getLocationMatchers } from 'app/features/geo/utils/location';
import { SpatialOperation, SpatialAction, SpatialTransformOptions } from './models.gen';
import { doGeomeryCalculation, toLineString } from './utils';
export const spatialTransformer: DataTransformerInfo<SpatialTransformOptions> = {
export const getSpatialTransformer: () => DataTransformerInfo<SpatialTransformOptions> = () => ({
id: DataTransformerID.spatial,
name: 'Spatial operations',
description: 'Apply spatial operations to query results.',
name: t('transformers.get-spatial-transformer.name.spatial-operations', 'Spatial operations'),
description: t(
'transformers.get-spatial-transformer.description.apply-spatial-operations-to-query-results',
'Apply spatial operations to query results.'
),
defaultOptions: {},
operator: (options) => (source) => source.pipe(mergeMap((data) => from(doSetGeometry(data, options)))),
};
});
export function isLineBuilderOption(options: SpatialTransformOptions): boolean {
return options.action === SpatialAction.Modify && options.modify?.op === SpatialOperation.LineBuilder;
@@ -1,74 +1,74 @@
import { TransformerRegistryItem } from '@grafana/data';
import { config } from '@grafana/runtime';
import { filterByValueTransformRegistryItem } from './FilterByValueTransformer/FilterByValueTransformerEditor';
import { heatmapTransformRegistryItem } from './calculateHeatmap/HeatmapTransformerEditor';
import { configFromQueryTransformRegistryItem } from './configFromQuery/ConfigFromQueryTransformerEditor';
import { calculateFieldTransformRegistryItem } from './editors/CalculateFieldTransformerEditor';
import { concatenateTransformRegistryItem } from './editors/ConcatenateTransformerEditor';
import { convertFieldTypeTransformRegistryItem } from './editors/ConvertFieldTypeTransformerEditor';
import { filterFieldsByNameTransformRegistryItem } from './editors/FilterByNameTransformerEditor';
import { filterFramesByRefIdTransformRegistryItem } from './editors/FilterByRefIdTransformerEditor';
import { formatStringTransformerRegistryItem } from './editors/FormatStringTransformerEditor';
import { formatTimeTransformerRegistryItem } from './editors/FormatTimeTransformerEditor';
import { groupByTransformRegistryItem } from './editors/GroupByTransformerEditor';
import { groupToNestedTableTransformRegistryItem } from './editors/GroupToNestedTableTransformerEditor';
import { groupingToMatrixTransformRegistryItem } from './editors/GroupingToMatrixTransformerEditor';
import { histogramTransformRegistryItem } from './editors/HistogramTransformerEditor';
import { joinByFieldTransformerRegistryItem } from './editors/JoinByFieldTransformerEditor';
import { labelsToFieldsTransformerRegistryItem } from './editors/LabelsToFieldsTransformerEditor';
import { limitTransformRegistryItem } from './editors/LimitTransformerEditor';
import { mergeTransformerRegistryItem } from './editors/MergeTransformerEditor';
import { organizeFieldsTransformRegistryItem } from './editors/OrganizeFieldsTransformerEditor';
import { reduceTransformRegistryItem } from './editors/ReduceTransformerEditor';
import { renameByRegexTransformRegistryItem } from './editors/RenameByRegexTransformer';
import { seriesToRowsTransformerRegistryItem } from './editors/SeriesToRowsTransformerEditor';
import { sortByTransformRegistryItem } from './editors/SortByTransformerEditor';
import { transposeTransformerRegistryItem } from './editors/TransposeTransformerEditor';
import { extractFieldsTransformRegistryItem } from './extractFields/ExtractFieldsTransformerEditor';
import { joinByLabelsTransformRegistryItem } from './joinByLabels/JoinByLabelsTransformerEditor';
import { fieldLookupTransformRegistryItem } from './lookupGazetteer/FieldLookupTransformerEditor';
import { partitionByValuesTransformRegistryItem } from './partitionByValues/PartitionByValuesEditor';
import { prepareTimeseriesTransformerRegistryItem } from './prepareTimeSeries/PrepareTimeSeriesEditor';
import { regressionTransformerRegistryItem } from './regression/regressionEditor';
import { rowsToFieldsTransformRegistryItem } from './rowsToFields/RowsToFieldsTransformerEditor';
import { spatialTransformRegistryItem } from './spatial/SpatialTransformerEditor';
import { timeSeriesTableTransformRegistryItem } from './timeSeriesTable/TimeSeriesTableTransformEditor';
import { getFilterByValueTransformRegistryItem } from './FilterByValueTransformer/FilterByValueTransformerEditor';
import { getHeatmapTransformRegistryItem } from './calculateHeatmap/HeatmapTransformerEditor';
import { getConfigFromQueryTransformRegistryItem } from './configFromQuery/ConfigFromQueryTransformerEditor';
import { getCalculateFieldTransformRegistryItem } from './editors/CalculateFieldTransformerEditor/CalculateFieldTransformerEditor';
import { getConcatenateTransformRegistryItem } from './editors/ConcatenateTransformerEditor';
import { getConvertFieldTypeTransformRegistryItem } from './editors/ConvertFieldTypeTransformerEditor';
import { getFilterFieldsByNameTransformRegistryItem } from './editors/FilterByNameTransformerEditor';
import { getFilterFramesByRefIdTransformRegistryItem } from './editors/FilterByRefIdTransformerEditor';
import { getFormatStringTransformerRegistryItem } from './editors/FormatStringTransformerEditor';
import { getFormatTimeTransformerRegistryItem } from './editors/FormatTimeTransformerEditor';
import { getGroupByTransformRegistryItem } from './editors/GroupByTransformerEditor';
import { getGroupToNestedTableTransformRegistryItem } from './editors/GroupToNestedTableTransformerEditor';
import { getGroupingToMatrixTransformRegistryItem } from './editors/GroupingToMatrixTransformerEditor';
import { getHistogramTransformRegistryItem } from './editors/HistogramTransformerEditor';
import { getJoinByFieldTransformerRegistryItem } from './editors/JoinByFieldTransformerEditor';
import { getLabelsToFieldsTransformerRegistryItem } from './editors/LabelsToFieldsTransformerEditor';
import { getLimitTransformRegistryItem } from './editors/LimitTransformerEditor';
import { getMergeTransformerRegistryItem } from './editors/MergeTransformerEditor';
import { getOrganizeFieldsTransformRegistryItem } from './editors/OrganizeFieldsTransformerEditor';
import { getReduceTransformRegistryItem } from './editors/ReduceTransformerEditor';
import { getRenameByRegexTransformRegistryItem } from './editors/RenameByRegexTransformer';
import { getSeriesToRowsTransformerRegistryItem } from './editors/SeriesToRowsTransformerEditor';
import { getSortByTransformRegistryItem } from './editors/SortByTransformerEditor';
import { getTransposeTransformerRegistryItem } from './editors/TransposeTransformerEditor';
import { getExtractFieldsTransformRegistryItem } from './extractFields/ExtractFieldsTransformerEditor';
import { getJoinByLabelsTransformRegistryItem } from './joinByLabels/JoinByLabelsTransformerEditor';
import { getFieldLookupTransformRegistryItem } from './lookupGazetteer/FieldLookupTransformerEditor';
import { getPartitionByValuesTransformRegistryItem } from './partitionByValues/PartitionByValuesEditor';
import { getPrepareTimeseriesTransformerRegistryItem } from './prepareTimeSeries/PrepareTimeSeriesEditor';
import { getRegressionTransformerRegistryItem } from './regression/regressionEditor';
import { getRowsToFieldsTransformRegistryItem } from './rowsToFields/RowsToFieldsTransformerEditor';
import { getSpatialTransformRegistryItem } from './spatial/SpatialTransformerEditor';
import { getTimeSeriesTableTransformRegistryItem } from './timeSeriesTable/TimeSeriesTableTransformEditor';
export const getStandardTransformers = (): TransformerRegistryItem[] => {
return [
reduceTransformRegistryItem,
filterFieldsByNameTransformRegistryItem,
renameByRegexTransformRegistryItem,
filterFramesByRefIdTransformRegistryItem,
filterByValueTransformRegistryItem,
organizeFieldsTransformRegistryItem,
joinByFieldTransformerRegistryItem,
seriesToRowsTransformerRegistryItem,
concatenateTransformRegistryItem,
calculateFieldTransformRegistryItem,
labelsToFieldsTransformerRegistryItem,
groupByTransformRegistryItem,
sortByTransformRegistryItem,
mergeTransformerRegistryItem,
histogramTransformRegistryItem,
rowsToFieldsTransformRegistryItem,
configFromQueryTransformRegistryItem,
prepareTimeseriesTransformerRegistryItem,
convertFieldTypeTransformRegistryItem,
spatialTransformRegistryItem,
fieldLookupTransformRegistryItem,
extractFieldsTransformRegistryItem,
heatmapTransformRegistryItem,
groupingToMatrixTransformRegistryItem,
limitTransformRegistryItem,
joinByLabelsTransformRegistryItem,
regressionTransformerRegistryItem,
partitionByValuesTransformRegistryItem,
...(config.featureToggles.formatString ? [formatStringTransformerRegistryItem] : []),
...(config.featureToggles.groupToNestedTableTransformation ? [groupToNestedTableTransformRegistryItem] : []),
formatTimeTransformerRegistryItem,
timeSeriesTableTransformRegistryItem,
transposeTransformerRegistryItem,
getReduceTransformRegistryItem(),
getFilterFieldsByNameTransformRegistryItem(),
getRenameByRegexTransformRegistryItem(),
getFilterFramesByRefIdTransformRegistryItem(),
getFilterByValueTransformRegistryItem(),
getOrganizeFieldsTransformRegistryItem(),
getJoinByFieldTransformerRegistryItem(),
getSeriesToRowsTransformerRegistryItem(),
getConcatenateTransformRegistryItem(),
getCalculateFieldTransformRegistryItem(),
getLabelsToFieldsTransformerRegistryItem(),
getGroupByTransformRegistryItem(),
getSortByTransformRegistryItem(),
getMergeTransformerRegistryItem(),
getHistogramTransformRegistryItem(),
getRowsToFieldsTransformRegistryItem(),
getConfigFromQueryTransformRegistryItem(),
getPrepareTimeseriesTransformerRegistryItem(),
getConvertFieldTypeTransformRegistryItem(),
getSpatialTransformRegistryItem(),
getFieldLookupTransformRegistryItem(),
getExtractFieldsTransformRegistryItem(),
getHeatmapTransformRegistryItem(),
getGroupingToMatrixTransformRegistryItem(),
getLimitTransformRegistryItem(),
getJoinByLabelsTransformRegistryItem(),
getRegressionTransformerRegistryItem(),
getPartitionByValuesTransformRegistryItem(),
...(config.featureToggles.formatString ? [getFormatStringTransformerRegistryItem()] : []),
...(config.featureToggles.groupToNestedTableTransformation ? [getGroupToNestedTableTransformRegistryItem()] : []),
getFormatTimeTransformerRegistryItem(),
getTimeSeriesTableTransformRegistryItem(),
getTransposeTransformerRegistryItem(),
];
};
@@ -17,7 +17,7 @@ import { InlineFieldRow, InlineField, StatsPicker, Select, InlineLabel } from '@
import { getTransformationContent } from '../docs/getTransformationContent';
import {
timeSeriesTableTransformer,
getTimeSeriesTableTransformer,
TimeSeriesTableTransformerOptions,
getRefData,
} from './timeSeriesTableTransformer';
@@ -123,12 +123,16 @@ export function TimeSeriesTableTransformEditor({
return <>{configRows}</>;
}
export const timeSeriesTableTransformRegistryItem: TransformerRegistryItem<TimeSeriesTableTransformerOptions> = {
id: timeSeriesTableTransformer.id,
editor: TimeSeriesTableTransformEditor,
transformation: timeSeriesTableTransformer,
name: timeSeriesTableTransformer.name,
description: timeSeriesTableTransformer.description,
state: PluginState.beta,
help: getTransformationContent(timeSeriesTableTransformer.id).helperDocs,
};
export const getTimeSeriesTableTransformRegistryItem: () => TransformerRegistryItem<TimeSeriesTableTransformerOptions> =
() => {
const timeSeriesTableTransformer = getTimeSeriesTableTransformer();
return {
id: timeSeriesTableTransformer.id,
editor: TimeSeriesTableTransformEditor,
transformation: timeSeriesTableTransformer,
name: timeSeriesTableTransformer.name,
description: timeSeriesTableTransformer.description,
state: PluginState.beta,
help: getTransformationContent(timeSeriesTableTransformer.id).helperDocs,
};
};
@@ -14,6 +14,7 @@ import {
TransformationApplicabilityLevels,
isTimeSeriesField,
} from '@grafana/data';
import { t } from '@grafana/i18n';
/**
* Maps a refId to a Field which can contain
@@ -81,10 +82,13 @@ export interface RefIdTransformerOptions {
inlineStat?: boolean;
}
export const timeSeriesTableTransformer: DataTransformerInfo<TimeSeriesTableTransformerOptions> = {
export const getTimeSeriesTableTransformer: () => DataTransformerInfo<TimeSeriesTableTransformerOptions> = () => ({
id: DataTransformerID.timeSeriesTable,
name: 'Time series to table',
description: 'Convert time series data to table rows so that they can be viewed in tabular or sparkline format.',
name: t('transformers.time-series-table.name.time-series-to-table', 'Time series to table'),
description: t(
'transformers.time-series-table.description.convert-to-table-rows',
'Convert time series data to table rows so that they can be viewed in tabular or sparkline format.'
),
defaultOptions: {},
isApplicable: (data) => {
for (const frame of data) {
@@ -95,15 +99,17 @@ export const timeSeriesTableTransformer: DataTransformerInfo<TimeSeriesTableTran
return TransformationApplicabilityLevels.NotApplicable;
},
isApplicableDescription:
'The Time series to table transformation requires at least one time series frame to function. You currently have none.',
isApplicableDescription: t(
'transformers.time-series-table.is-applicable-description.requires-time-series-frame',
'The Time series to table transformation requires at least one time series frame to function. You currently have none.'
),
operator: (options) => (source) =>
source.pipe(
map((data) => {
return timeSeriesToTableTransform(options, data);
})
),
};
});
/**
* Converts time series frames to table frames for use with sparkline chart type.
+15 -9
View File
@@ -62,15 +62,21 @@ export function getDistinctLabels(input: DataFrame[]): Set<string> {
return distinct;
}
export const categoriesLabels: { [K in TransformerCategory]: string } = {
combine: 'Combine',
calculateNewFields: 'Calculate new fields',
createNewVisualization: 'Create new visualization',
filter: 'Filter',
performSpatialOperations: 'Perform spatial operations',
reformat: 'Reformat',
reorderAndRename: 'Reorder and rename',
};
export const getCategoriesLabels: () => { [K in TransformerCategory]: string } = () => ({
combine: t('transformers.utils.get-categories-labels.combine', 'Combine'),
calculateNewFields: t('transformers.utils.get-categories-labels.calculate-new-fields', 'Calculate new fields'),
createNewVisualization: t(
'transformers.utils.get-categories-labels.create-new-visualization',
'Create new visualization'
),
filter: t('transformers.utils.get-categories-labels.filter', 'Filter'),
performSpatialOperations: t(
'transformers.utils.get-categories-labels.perform-spatial-operations',
'Perform spatial operations'
),
reformat: t('transformers.utils.get-categories-labels.reformat', 'Reformat'),
reorderAndRename: t('transformers.utils.get-categories-labels.reorder-and-rename', 'Reorder and rename'),
});
export const numberOrVariableValidator = (value: string | number) => {
if (typeof value === 'number') {
+339 -8
View File
@@ -5259,7 +5259,8 @@
"transformation-picker-ng": {
"placeholder-search-for-transformation": "Search for transformation",
"show-images": "Show images",
"title-add-another-transformation": "Add another transformation"
"title-add-another-transformation": "Add another transformation",
"view-all": "View all"
},
"un-theme-transformations-editor": {
"body-delete-all-transformations": "By deleting all transformations, you will go back to the main selection screen."
@@ -12230,6 +12231,18 @@
"placeholder-fields-or-number": "Field(s) or number"
},
"calculate-field-transformer-editor": {
"calculation-modes": {
"label": {
"binary-operation": "Binary operation",
"reduce-row": "Reduce row",
"row-index": "Row index",
"unary-operation": "Unary operation"
}
},
"label": {
"cumulative-functions": "Cumulative functions",
"window-functions": "Window functions"
},
"label-alias": "Alias",
"label-mode": "Mode",
"label-replace-all-fields": "Replace all fields"
@@ -12244,6 +12257,13 @@
"concatenate-transformer-editor": {
"label-label": "Label",
"label-name": "Name",
"name-modes": {
"label": {
"copy-frame-name-to-field": "Copy frame name to field name",
"ignore-the-frame-name": "Ignore the frame name",
"label-frame": "Add a label with the frame name"
}
},
"placeholder-frame": "Frame"
},
"config-from-query-transformer-editor": {
@@ -12255,6 +12275,9 @@
"aria-label-add-a-convert-field-type-transformer": "Add a convert field type transformer",
"aria-label-remove-convert-field-type-transformer": "Remove convert field type transformer",
"convert-field-type": "Convert field type",
"description": {
"convert-to-specified-field-type": "Convert a field to a specified field type."
},
"label": {
"browser": "Browser",
"utc": "UTC"
@@ -12265,7 +12288,13 @@
"label-input-format": "Input format",
"label-join-with": "Join with",
"label-set-timezone": "Set timezone",
"name": {
"convert-field-type": "Convert field type"
},
"placeholder-type": "Type",
"tags": {
"format-field": "Format field"
},
"tooltip-explicit-separator-joining-array-values": "Use an explicit separator when joining array values",
"tooltip-input-format": "Specify the format of the input field so Grafana can parse the date string correctly.",
"tooltip-specify-the-output-format": "Specify the output format.",
@@ -12287,6 +12316,19 @@
"desc": "DESC",
"off": "Off"
},
"editors": {
"concatenate-transformer-editor": {
"description": {
"combine-all-fields": "Combine all fields into a single frame."
},
"name": {
"concatenate-fields": "Concatenate fields"
},
"tags": {
"combine": "Combine"
}
}
},
"enum-mapping-editor": {
"add-enum-value": "Add enum value",
"generate-enum-values-from-data": "Generate enum values from data"
@@ -12297,6 +12339,9 @@
"remove-enum-row-tooltip-delete": "Delete"
},
"extract-fields-transformer-editor": {
"description": {
"parse-fields-from-content": "Parse fields from content (JSON, labels, etc)."
},
"field-name-picker-settings": {
"placeholderText": {
"select-field": "Select field"
@@ -12307,6 +12352,9 @@
"label-keep-time": "Keep time",
"label-replace-all-fields": "Replace all fields",
"label-source": "Source",
"name": {
"extract-fields": "Extract fields"
},
"placeholder-auto": "Auto",
"placeholder-select-delimiter": "Select delimiter...",
"tooltip-regexp": "Example: {{regexExample}}"
@@ -12315,6 +12363,9 @@
"aria-label-threshold-color": "Threshold color"
},
"field-lookup-transformer-editor": {
"description": {
"lookup-additional-fields-external-source": "Use a field value to lookup countries, states, or airports."
},
"field-name-picker-settings": {
"noFieldsMessage": {
"no-text-fields-found": "No text fields found"
@@ -12324,7 +12375,10 @@
}
},
"label-field": "Field",
"label-lookup": "Lookup"
"label-lookup": "Lookup",
"name": {
"lookup-fields-from-resource": "Lookup fields from resource"
}
},
"field-to-config-mapping-editor": {
"additional-settings": "Additional settings",
@@ -12333,12 +12387,26 @@
"use-as": "Use as"
},
"filter-by-name-transformer-editor": {
"description": {
"remove-part-query-results-regex-pattern": "Remove parts of the query results using a regex pattern."
},
"label-from-variable": "From variable",
"label-identifier": "Identifier",
"label-use-variable": "Use variable",
"label-variable": "Variable",
"name": {
"filter-fields-by-name": "Filter fields by name"
},
"placeholder-regular-expression-pattern": "Regular expression pattern"
},
"filter-by-ref-id-transformer-editor": {
"description": {
"filter-data-by-query-useful-sharing-results": "Remove rows from the data based on origin query"
},
"name": {
"filter-data-by-query": "Filter data by query"
}
},
"filter-by-value-filter-editor": {
"label-field": "Field",
"label-match": "Match",
@@ -12348,6 +12416,9 @@
},
"filter-by-value-transformer-editor": {
"add-condition": "Add condition",
"description": {
"remove-rows-query-results-user-defined-filters": "Remove rows from the query results using user-defined filters."
},
"filter-match": {
"label": {
"match-all": "Match all",
@@ -12361,7 +12432,10 @@
}
},
"label-conditions": "Conditions",
"label-filter-type": "Filter type"
"label-filter-type": "Filter type",
"name": {
"filter-data-by-values": "Filter data by values"
}
},
"format-string-transfomer-editor": {
"field-name-picker-settings": {
@@ -12376,6 +12450,14 @@
"label-format": "Format",
"label-substring-range": "Substring range"
},
"format-string-transformer-editor": {
"description": {
"manipulate-string-fields-formatting": "Manipulate string fields formatting."
},
"name": {
"format-string": "Format string"
}
},
"format-time-transfomer-editor": {
"label-format": "Format",
"label-set-timezone": "Set timezone",
@@ -12383,6 +12465,70 @@
"tooltip-format": "The output format for the field specified as a <2>Moment.js format string</2>.",
"tooltip-timezone-manually": "Set the timezone of the date manually"
},
"format-time-transformer-editor": {
"description": {
"set-based-on-time": "Set the output format of a time field"
},
"name": {
"format-time": "Format time"
}
},
"get-calculate-field-transform-registry-item": {
"description": {
"values-calculate-field": "Use the row values to calculate a new field."
},
"name": {
"add-field-from-calculation": "Add field from calculation"
}
},
"get-config-from-data-transformer": {
"description": {
"set-unit-min-max-and-more": "Set unit, min, max and more."
},
"name": {
"config-from-query-results": "Config from query results"
}
},
"get-heatmap-transformer": {
"description": {
"generate-heatmap-data-from-source": "Generate heatmap data from source data."
},
"name": {
"create-heatmap": "Create heatmap"
}
},
"get-join-by-labels-transformer": {
"description": {
"flatten-labeled-results-table-joined-labels": "Flatten labeled results into a table joined by labels."
},
"name": {
"join-by-labels": "Join by labels"
}
},
"get-partition-by-values-transformer": {
"description": {
"split-oneframe-dataset-multiple-series": "Split a one-frame dataset into multiple series."
},
"name": {
"partition-by-values": "Partition by values"
}
},
"get-rows-to-fields-transformer": {
"description": {
"convert-field-dynamic-config": "Convert each row into a field with dynamic config."
},
"name": {
"rows-to-fields": "Rows to fields"
}
},
"get-spatial-transformer": {
"description": {
"apply-spatial-operations-to-query-results": "Apply spatial operations to query results."
},
"name": {
"spatial-operations": "Spatial operations"
}
},
"get-timezone-options": {
"label": {
"browser": "Browser",
@@ -12410,22 +12556,46 @@
}
},
"group-by-field-configuration": {
"options": {
"label": {
"calculate": "Calculate",
"group-by": "Group by"
}
},
"placeholder-ignored": "Ignored",
"placeholder-select-stats": "Select stats"
},
"group-by-transformer-editor": {
"description": {
"group-series-by-field-calculate-stats": "Group data by a field value and create aggregate data."
},
"name": {
"group-by": "Group by"
},
"title-calc-alert": "Calculations will not have an effect if no fields are being grouped on"
},
"group-to-nested-table-transformer-editor": {
"description": {
"group-by-field-value": "Group data by a field value and create nested tables with the grouped data."
},
"description-show-field-names": "If enabled nested tables will show field names as a table header",
"label-show-field-names-in-nested-tables": "Show field names in nested tables",
"name": {
"group-to-nested-tables": "Group to nested tables"
},
"title-calc-alert": "Calculations will not have an effect if no fields are being grouped on."
},
"grouping-to-matrix-transformer-editor": {
"description": {
"summarize-and-reorganize-data": "Summarize and reorganize data based on three fields."
},
"label-cell-value": "Cell value",
"label-column": "Column",
"label-empty-value": "Empty value",
"label-row": "Row",
"name": {
"grouping-to-matrix": "Grouping to matrix"
},
"special-value-options": {
"description": {
"boolean-false-value": "Boolean false value",
@@ -12444,6 +12614,12 @@
}
},
"histogram-transformer-editor": {
"description": {
"calculate-histogram-from-input-data": "Calculate a histogram from input data."
},
"name": {
"histogram": "Histogram"
},
"placeholder-auto": "Auto",
"placeholder-default": "Default: 30",
"placeholder-none": "None"
@@ -12452,7 +12628,16 @@
"label-as-percentile": "As percentile",
"tooltip-transform-index-percentile": "Transform the row index as a percentile."
},
"join-by-field-transformer-editor": {
"description": {
"combine-rows-from-2-tables": "Combine rows from 2+ tables, based on a related field."
},
"name": {
"join-by-field": "Join by field"
}
},
"join-by-labels-transformer-editor": {
"error-required": "Required",
"info": {
"input-contain-labels": "The input does not contain any labels",
"no-input-or-labels-found": "No input (or labels) found",
@@ -12474,10 +12659,30 @@
"label-labels": "Labels",
"label-mode": "Mode",
"label-value-field-name": "Value field name",
"modes": {
"label": {
"columns": "Columns",
"rows": "Rows"
}
},
"placeholder-optional-select-label": "(Optional) Select label",
"tooltip-replace-value-field-label": "Replace the value field name with a label"
},
"labels-to-fields-transformer-editor": {
"description": {
"groups-series-time-return-labels-tags-fields": "Group series by time and return labels or tags as fields."
},
"name": {
"labels-to-fields": "Labels to fields"
}
},
"limit-transformer-editor": {
"description": {
"limit-number-items-displayed": "Limit the number of items displayed."
},
"name": {
"limit": "Limit"
},
"placeholder-value-or-variable": "Value or variable"
},
"long-info": {
@@ -12488,7 +12693,13 @@
"string-values-separate": "String values are represented as separate fields rather than as labels"
},
"merge-transformer-editor": {
"merge-effect-applied-single-frame": "Merge has no effect when applied on a single frame."
"description": {
"merge-multiple-series": "Merge multiple series. Values will be combined into one row."
},
"merge-effect-applied-single-frame": "Merge has no effect when applied on a single frame.",
"name": {
"merge": "Merge series/tables"
}
},
"multi-info": {
"all-values-are-numeric": "All values are numeric",
@@ -12498,10 +12709,16 @@
"time-in-ascending-order": "Time in ascending order"
},
"organize-fields-transformer-editor": {
"description": {
"reorder-hide-or-rename-fields": "Re-order, hide, or rename fields."
},
"field-order": "Field order",
"field-order-auto": "Auto",
"field-order-manual": "Manual",
"first-frame-warning": "Organize fields only works with a single frame. Consider applying a join transformation or filtering the input first."
"first-frame-warning": "Organize fields only works with a single frame. Consider applying a join transformation or filtering the input first.",
"name": {
"organize-fields": "Organize fields by name"
}
},
"partion-by-values-editor": {
"tooltip-naming": "Sets how the names of the selected fields are displayed. As frame name is usually better for tabular data"
@@ -12526,9 +12743,41 @@
"partition-values-works-single-frame": "Partition by values only works with a single frame.",
"tooltip-keeps-partition-fields-frames": "Keeps the partition fields in the frames"
},
"prepare-time-series": {
"description": {
"stretch-data-frames": "Stretch data frames from the wide format into the long format."
},
"name": {
"prepare-time-series": "Prepare time series"
}
},
"prepare-time-series-editor": {
"label-format": "Format",
"label-info": "Info"
"label-info": "Info",
"long-info": {
"description": {
"convert-each-frame-to-long-format": "Convert each frame to long format"
},
"label": {
"long-time-series": "Long time series"
}
},
"multi-info": {
"description": {
"creates-frame-timenumber": "Creates a new frame for each time/number pair"
},
"label": {
"multiframe-time-series": "Multi-frame time series"
}
},
"wide-info": {
"description": {
"creates-single-frame-joined": "Creates a single frame joined by time"
},
"label": {
"wide-time-series": "Wide time series"
}
}
},
"range-matcher-editor": {
"and": "and",
@@ -12540,6 +12789,9 @@
"label-operation": "Operation"
},
"reduce-transformer-editor": {
"description": {
"reduce-to-single-value": "Reduce all rows or data points to a single value (ex. max, mean)."
},
"label-calculations": "Calculations",
"label-include-time": "Include time",
"label-labels-to-fields": "Labels to fields",
@@ -12554,12 +12806,23 @@
"series-to-rows": "Series to rows"
}
},
"name": {
"reduce": "Reduce"
},
"placeholder-choose-stat": "Choose stat"
},
"regex-matcher-editor": {
"placeholder-value-or-variable": "Value or variable",
"variable-regex-documentation": "Formats multi-value variable into a regex string"
},
"regression": {
"description": {
"create-new-data-frame": "Create a new data frame containing values predicted by a statistical model."
},
"name": {
"regression-analysis": "Regression analysis"
}
},
"regression-transformer-editor": {
"label": {
"cubic": "Cubic",
@@ -12581,6 +12844,14 @@
"regression": "regression",
"tooltip-number-of-xy-points-to-predict": "Number of X,Y points to predict"
},
"rename-by-regex-transformer": {
"description": {
"rename-parts-using-regex": "Rename parts of the query results using a regular expression and replacement pattern."
},
"name": {
"rename-fields-by-regex": "Rename fields by regex"
}
},
"rename-by-regex-transformer-editor": {
"label-match": "Match",
"label-replace": "Replace",
@@ -12589,11 +12860,37 @@
},
"series-to-fields-transformer-editor": {
"label-field": "Field",
"label-mode": "Mode"
"label-mode": "Mode",
"modes": {
"description": {
"combine-data-from-two-tables": "Combine data from two tables whenever there are matching values in a fields common to both tables.",
"join-on-a-field": "Join on a field value with duplicated values. Non performant outer join best used for tabular(SQL like) data.",
"keep-all-rows": "Keep all rows from any table with a value. Join on distinct field values. Performant and best used for time series."
},
"label": {
"inner": "Inner",
"outer-tabular": "Outer (tabular)",
"outer-time-series": "Outer (time series)"
}
}
},
"series-to-rows-transformer-editor": {
"description": {
"merge-multiple-series": "Merge multiple series. Return time, metric and values as a row."
},
"name": {
"series-to-rows": "Series to rows"
}
},
"sort-by-transformer-editor": {
"description": {
"sort-fields": "Sort fields in a frame."
},
"label-field": "Field",
"label-reverse": "Reverse",
"name": {
"sort-by": "Sort by"
},
"placeholder-select-field": "Select field"
},
"supplier": {
@@ -12613,7 +12910,17 @@
"transform": "Transform"
}
},
"tag": "{{ tag }}",
"time-series-table": {
"description": {
"convert-to-table-rows": "Convert time series data to table rows so that they can be viewed in tabular or sparkline format."
},
"is-applicable-description": {
"requires-time-series-frame": "The Time series to table transformation requires at least one time series frame to function. You currently have none."
},
"name": {
"time-series-to-table": "Time series to table"
}
},
"time-series-table-transform-editor": {
"label-stat": "Stat",
"label-time-field": "Time field",
@@ -12627,10 +12934,34 @@
"placeholder-value": "Value",
"tooltip-name-for-value-fields": "Name for value fields"
},
"transpose-transformer-editor": {
"description": {
"transpose-data-frame": "Transpose the data frame."
},
"name": {
"transpose": "Transpose"
},
"tags": {
"pivot": "Pivot",
"transform": "Transform",
"translate": "Translate"
}
},
"unary-operation-editor": {
"label-operation": "Operation",
"placeholder-field": "Field"
},
"utils": {
"get-categories-labels": {
"calculate-new-fields": "Calculate new fields",
"combine": "Combine",
"create-new-visualization": "Create new visualization",
"filter": "Filter",
"perform-spatial-operations": "Perform spatial operations",
"reformat": "Reformat",
"reorder-and-rename": "Reorder and rename"
}
},
"wide-info": {
"multiple-value-fields-of-any-type": "Multiple value fields of any type",
"single-frame": "Single frame",