/usr/share/grafana/public/app/features/transformers/timeSeriesTable
import { useCallback } from 'react'; import { PluginState, TransformerRegistryItem, TransformerUIProps, ReducerID, isReducerID, SelectableValue, Field, FieldType, isTimeSeriesField, } from '@grafana/data'; import { t } from '@grafana/i18n'; import { InlineFieldRow, InlineField, StatsPicker, Select, InlineLabel } from '@grafana/ui'; import { getTransformationContent } from '../docs/getTransformationContent'; import darkImage from '../images/dark/timeSeriesTable.svg'; import lightImage from '../images/light/timeSeriesTable.svg'; import { getTimeSeriesTableTransformer, TimeSeriesTableTransformerOptions, getRefData, } from './timeSeriesTableTransformer'; export function TimeSeriesTableTransformEditor({ input, options, onChange, }: TransformerUIProps<TimeSeriesTableTransformerOptions>) { const refIdMap = getRefData(input); const onSelectTimefield = useCallback( (refId: string, value: SelectableValue<string>) => { const val = value?.value !== undefined ? value.value : ''; onChange({ ...options, [refId]: { ...options[refId], timeField: val, }, }); }, [onChange, options] ); const onSelectStat = useCallback( (refId: string, stats: string[]) => { const reducerID = stats[0]; if (reducerID && isReducerID(reducerID)) { onChange({ ...options, [refId]: { ...options[refId], stat: reducerID, }, }); } }, [onChange, options] ); let configRows = []; for (const refId of Object.keys(refIdMap)) { // Get time fields for the current refId const timeFields: Record<string, Field<FieldType.time>> = {}; const timeValues: Array<SelectableValue<string>> = []; // Get a map of time fields, we map // by field name and assume that time fields // in the same query with the same name // are the same for (const frame of input) { if (frame.refId === refId) { for (const field of frame.fields) { if (isTimeSeriesField(field)) { timeFields[field.name] = field; } } } } for (const timeField of Object.values(timeFields)) { const { name } = timeField; timeValues.push({ label: name, value: name }); } configRows.push( <InlineFieldRow key={refId}> <InlineField> <InlineLabel>{`Trend #${refId}`}</InlineLabel> </InlineField> <InlineField label={t('transformers.time-series-table-transform-editor.label-time-field', 'Time field')} tooltip={t( 'transformers.time-series-table-transform-editor.tooltip-time-field', 'The time field that will be used for the time series. If not selected the first found will be used.' )} > <Select onChange={onSelectTimefield.bind(null, refId)} options={timeValues} value={options[refId]?.timeField} isClearable={true} /> </InlineField> <InlineField label={t('transformers.time-series-table-transform-editor.label-stat', 'Stat')} tooltip={t( 'transformers.time-series-table-transform-editor.tooltip-statistic-should-calculated-series', 'The statistic that should be calculated for this time series.' )} > <StatsPicker stats={[options[refId]?.stat ?? ReducerID.lastNotNull]} onChange={onSelectStat.bind(null, refId)} filterOptions={(ext) => ext.id !== ReducerID.allValues && ext.id !== ReducerID.uniqueValues} /> </InlineField> </InlineFieldRow> ); } return <>{configRows}</>; } 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, imageDark: darkImage, imageLight: lightImage, }; };
.
Edit
..
Edit
TimeSeriesTableTransformEditor.tsx
Edit
timeSeriesTableTransformer.test.ts
Edit
timeSeriesTableTransformer.ts
Edit