Transformations: Convert field types to time string number or boolean (#38517)

* outline string to time

add stringToTime transformer

start to add format

add type and dateformat

rename stringToTime to fieldConversion

add more type support and use FieldNamePicker

add field conversion transformation

* adjust for performance feedback

rename and adjust labels and widths

shorten labels and null values

rename to convertFieldType

update test

* make updates
This commit is contained in:
nikki-kiga
2021-08-27 13:49:31 -07:00
committed by GitHub
parent 3c72f1678f
commit a54a139176
10 changed files with 574 additions and 11 deletions

View File

@@ -0,0 +1,149 @@
import React, { useCallback } from 'react';
import {
DataTransformerID,
FieldNamePickerConfigSettings,
FieldType,
SelectableValue,
StandardEditorsRegistryItem,
standardTransformers,
TransformerRegistryItem,
TransformerUIProps,
} from '@grafana/data';
import { ConvertFieldTypeTransformerOptions } from '@grafana/data/src/transformations/transformers/convertFieldType';
import { Button, InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
import { FieldNamePicker } from '../../../../../packages/grafana-ui/src/components/MatchersUI/FieldNamePicker';
import { ConvertFieldTypeOptions } from '../../../../../packages/grafana-data/src/transformations/transformers/convertFieldType';
const fieldNamePickerSettings: StandardEditorsRegistryItem<string, FieldNamePickerConfigSettings> = {
settings: { width: 24 },
} as any;
export const ConvertFieldTypeTransformerEditor: React.FC<TransformerUIProps<ConvertFieldTypeTransformerOptions>> = ({
input,
options,
onChange,
}) => {
const allTypes: Array<SelectableValue<FieldType>> = [
{ value: FieldType.number, label: 'Numeric' },
{ value: FieldType.string, label: 'String' },
{ value: FieldType.time, label: 'Time' },
{ value: FieldType.boolean, label: 'Boolean' },
];
const onSelectField = useCallback(
(idx) => (value: string | undefined) => {
const conversions = options.conversions;
conversions[idx] = { ...conversions[idx], targetField: value ?? '' };
onChange({
...options,
conversions: conversions,
});
},
[onChange, options]
);
const onSelectDestinationType = useCallback(
(idx) => (value: SelectableValue<FieldType>) => {
const conversions = options.conversions;
conversions[idx] = { ...conversions[idx], destinationType: value.value };
onChange({
...options,
conversions: conversions,
});
},
[onChange, options]
);
const onInputFormat = useCallback(
(idx) => (value: SelectableValue<string>) => {
const conversions = options.conversions;
conversions[idx] = { ...conversions[idx], dateFormat: value.value };
onChange({
...options,
conversions: conversions,
});
},
[onChange, options]
);
const onAddConvertFieldType = useCallback(() => {
onChange({
...options,
conversions: [
...options.conversions,
{ targetField: undefined, destinationType: undefined, dateFormat: undefined },
],
});
}, [onChange, options]);
const onRemoveConvertFieldType = useCallback(
(idx) => {
const removed = options.conversions;
removed.splice(idx, 1);
onChange({
...options,
conversions: removed,
});
},
[onChange, options]
);
return (
<>
{options.conversions.map((c: ConvertFieldTypeOptions, idx: number) => {
return (
<InlineFieldRow key={`${c.targetField}-${idx}`}>
<InlineField label={'Field'}>
<FieldNamePicker
context={{ data: input }}
value={c.targetField ?? ''}
onChange={onSelectField(idx)}
item={fieldNamePickerSettings}
/>
</InlineField>
<InlineField label={'as'}>
<Select
menuShouldPortal
options={allTypes}
value={c.destinationType}
placeholder={'Type'}
onChange={onSelectDestinationType(idx)}
width={18}
/>
</InlineField>
{c.destinationType === FieldType.time && (
<InlineField label={'Date Format'}>
<Input value={c.dateFormat} placeholder={'e.g. YYYY-MM-DD'} onChange={onInputFormat(idx)} width={24} />
</InlineField>
)}
<Button
size="md"
icon="trash-alt"
variant="secondary"
onClick={() => onRemoveConvertFieldType(idx)}
aria-label={'Remove convert field type transformer'}
/>
</InlineFieldRow>
);
})}
<Button
size="sm"
icon="plus"
onClick={onAddConvertFieldType}
variant="secondary"
aria-label={'Add a convert field type transformer'}
>
{'Convert field type'}
</Button>
</>
);
};
export const convertFieldTypeTransformRegistryItem: TransformerRegistryItem<ConvertFieldTypeTransformerOptions> = {
id: DataTransformerID.convertFieldType,
editor: ConvertFieldTypeTransformerEditor,
transformation: standardTransformers.convertFieldTypeTransformer,
name: standardTransformers.convertFieldTypeTransformer.name,
description: standardTransformers.convertFieldTypeTransformer.description,
};

View File

@@ -17,6 +17,7 @@ import { histogramTransformRegistryItem } from '../components/TransformersUI/His
import { rowsToFieldsTransformRegistryItem } from '../components/TransformersUI/rowsToFields/RowsToFieldsTransformerEditor';
import { configFromQueryTransformRegistryItem } from '../components/TransformersUI/configFromQuery/ConfigFromQueryTransformerEditor';
import { prepareTimeseriesTransformerRegistryItem } from '../components/TransformersUI/prepareTimeSeries/PrepareTimeSeriesEditor';
import { convertFieldTypeTransformRegistryItem } from '../components/TransformersUI/ConvertFieldTypeTransformerEditor';
export const getStandardTransformers = (): Array<TransformerRegistryItem<any>> => {
return [
@@ -38,5 +39,6 @@ export const getStandardTransformers = (): Array<TransformerRegistryItem<any>> =
rowsToFieldsTransformRegistryItem,
configFromQueryTransformRegistryItem,
prepareTimeseriesTransformerRegistryItem,
convertFieldTypeTransformRegistryItem,
];
};