mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Transformations: Support time format when converting time to strings (#63826)
This commit is contained in:
parent
bc1c54ca17
commit
a4fc8b9fca
@ -338,6 +338,31 @@ describe('field convert types transformer', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('will convert time fields to strings', () => {
|
||||||
|
const options = {
|
||||||
|
conversions: [{ targetField: 'time', destinationType: FieldType.string, dateFormat: 'YYYY-MM' }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const stringified = convertFieldTypes(options, [
|
||||||
|
toDataFrame({
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'time',
|
||||||
|
type: FieldType.time,
|
||||||
|
values: [1626674400000, 1627020000000, 1627192800000, 1627797600000, 1627884000000],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])[0].fields[0];
|
||||||
|
expect(stringified.values.toArray()).toEqual([
|
||||||
|
'2021-07',
|
||||||
|
'2021-07',
|
||||||
|
'2021-07', // can group by month
|
||||||
|
'2021-08',
|
||||||
|
'2021-08',
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ensureTimeField', () => {
|
describe('ensureTimeField', () => {
|
||||||
|
@ -98,7 +98,7 @@ export function convertFieldType(field: Field, opts: ConvertFieldTypeOptions): F
|
|||||||
case FieldType.number:
|
case FieldType.number:
|
||||||
return fieldToNumberField(field);
|
return fieldToNumberField(field);
|
||||||
case FieldType.string:
|
case FieldType.string:
|
||||||
return fieldToStringField(field);
|
return fieldToStringField(field, opts.dateFormat);
|
||||||
case FieldType.boolean:
|
case FieldType.boolean:
|
||||||
return fieldToBooleanField(field);
|
return fieldToBooleanField(field);
|
||||||
case FieldType.other:
|
case FieldType.other:
|
||||||
@ -179,17 +179,26 @@ function fieldToBooleanField(field: Field): Field {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function fieldToStringField(field: Field): Field {
|
function fieldToStringField(field: Field, dateFormat?: string): Field {
|
||||||
const stringValues = field.values.toArray().slice();
|
let values = field.values.toArray();
|
||||||
|
|
||||||
for (let s = 0; s < stringValues.length; s++) {
|
switch (field.type) {
|
||||||
stringValues[s] = `${stringValues[s]}`;
|
case FieldType.time:
|
||||||
|
values = values.map((v) => dateTimeParse(v).format(dateFormat));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FieldType.other:
|
||||||
|
values = values.map((v) => JSON.stringify(v));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
values = values.map((v) => `${v}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...field,
|
...field,
|
||||||
type: FieldType.string,
|
type: FieldType.string,
|
||||||
values: new ArrayVector(stringValues),
|
values: new ArrayVector(values),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,10 @@ export type IconSize = ComponentSize | 'xl' | 'xxl' | 'xxxl';
|
|||||||
// function remains for backwards compatibility
|
// function remains for backwards compatibility
|
||||||
export const getAvailableIcons = () => Object.keys(availableIconsIndex);
|
export const getAvailableIcons = () => Object.keys(availableIconsIndex);
|
||||||
|
|
||||||
/** Get the icon for a given field type */
|
/**
|
||||||
|
* Get the icon for a given field type
|
||||||
|
* @deprecated use getFieldTypeIconName
|
||||||
|
*/
|
||||||
export function getFieldTypeIcon(field?: Field): IconName {
|
export function getFieldTypeIcon(field?: Field): IconName {
|
||||||
if (field) {
|
if (field) {
|
||||||
switch (field.type) {
|
switch (field.type) {
|
||||||
@ -34,3 +37,24 @@ export function getFieldTypeIcon(field?: Field): IconName {
|
|||||||
}
|
}
|
||||||
return 'question-circle';
|
return 'question-circle';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get the icon for a given field type */
|
||||||
|
export function getFieldTypeIconName(fieldType?: FieldType): IconName {
|
||||||
|
switch (fieldType) {
|
||||||
|
case FieldType.time:
|
||||||
|
return 'clock-nine';
|
||||||
|
case FieldType.string:
|
||||||
|
return 'font';
|
||||||
|
case FieldType.number:
|
||||||
|
return 'calculator-alt';
|
||||||
|
case FieldType.boolean:
|
||||||
|
return 'toggle-on';
|
||||||
|
case FieldType.trace:
|
||||||
|
return 'info-circle';
|
||||||
|
case FieldType.geo:
|
||||||
|
return 'map-marker';
|
||||||
|
case FieldType.other:
|
||||||
|
return 'brackets-curly';
|
||||||
|
}
|
||||||
|
return 'question-circle';
|
||||||
|
}
|
||||||
|
@ -14,8 +14,9 @@ import {
|
|||||||
ConvertFieldTypeOptions,
|
ConvertFieldTypeOptions,
|
||||||
ConvertFieldTypeTransformerOptions,
|
ConvertFieldTypeTransformerOptions,
|
||||||
} from '@grafana/data/src/transformations/transformers/convertFieldType';
|
} from '@grafana/data/src/transformations/transformers/convertFieldType';
|
||||||
import { Button, InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
|
import { Button, InlineField, InlineFieldRow, Input, Select, getFieldTypeIconName } from '@grafana/ui';
|
||||||
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
|
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
|
||||||
|
import { findField } from 'app/features/dimensions';
|
||||||
|
|
||||||
const fieldNamePickerSettings: StandardEditorsRegistryItem<string, FieldNamePickerConfigSettings> = {
|
const fieldNamePickerSettings: StandardEditorsRegistryItem<string, FieldNamePickerConfigSettings> = {
|
||||||
settings: { width: 24, isClearable: false },
|
settings: { width: 24, isClearable: false },
|
||||||
@ -27,11 +28,11 @@ export const ConvertFieldTypeTransformerEditor = ({
|
|||||||
onChange,
|
onChange,
|
||||||
}: TransformerUIProps<ConvertFieldTypeTransformerOptions>) => {
|
}: TransformerUIProps<ConvertFieldTypeTransformerOptions>) => {
|
||||||
const allTypes: Array<SelectableValue<FieldType>> = [
|
const allTypes: Array<SelectableValue<FieldType>> = [
|
||||||
{ value: FieldType.number, label: 'Numeric' },
|
{ value: FieldType.number, label: 'Number', icon: getFieldTypeIconName(FieldType.number) },
|
||||||
{ value: FieldType.string, label: 'String' },
|
{ value: FieldType.string, label: 'String', icon: getFieldTypeIconName(FieldType.string) },
|
||||||
{ value: FieldType.time, label: 'Time' },
|
{ value: FieldType.time, label: 'Time', icon: getFieldTypeIconName(FieldType.time) },
|
||||||
{ value: FieldType.boolean, label: 'Boolean' },
|
{ value: FieldType.boolean, label: 'Boolean', icon: getFieldTypeIconName(FieldType.boolean) },
|
||||||
{ value: FieldType.other, label: 'JSON' },
|
{ value: FieldType.other, label: 'JSON', icon: getFieldTypeIconName(FieldType.other) },
|
||||||
];
|
];
|
||||||
|
|
||||||
const onSelectField = useCallback(
|
const onSelectField = useCallback(
|
||||||
@ -122,6 +123,11 @@ export const ConvertFieldTypeTransformerEditor = ({
|
|||||||
<Input value={c.dateFormat} placeholder={'e.g. YYYY-MM-DD'} onChange={onInputFormat(idx)} width={24} />
|
<Input value={c.dateFormat} placeholder={'e.g. YYYY-MM-DD'} onChange={onInputFormat(idx)} width={24} />
|
||||||
</InlineField>
|
</InlineField>
|
||||||
)}
|
)}
|
||||||
|
{c.destinationType === FieldType.string && (c.dateFormat || findField(input?.[0], c.targetField)) && (
|
||||||
|
<InlineField label="Date format" tooltip="Specify the output format.">
|
||||||
|
<Input value={c.dateFormat} placeholder={'e.g. YYYY-MM-DD'} onChange={onInputFormat(idx)} width={24} />
|
||||||
|
</InlineField>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
size="md"
|
size="md"
|
||||||
icon="trash-alt"
|
icon="trash-alt"
|
||||||
|
Loading…
Reference in New Issue
Block a user