diff --git a/packages/grafana-data/src/transformations/index.ts b/packages/grafana-data/src/transformations/index.ts index 82659a2885c..c21e8dfd428 100644 --- a/packages/grafana-data/src/transformations/index.ts +++ b/packages/grafana-data/src/transformations/index.ts @@ -1,10 +1,16 @@ export * from './matchers/ids'; export * from './transformers/ids'; export * from './matchers'; -export * from './transformers'; +export { standardTransformers } from './transformers'; export * from './fieldReducer'; export { FilterFieldsByNameTransformerOptions } from './transformers/filterByName'; export { FilterFramesByRefIdTransformerOptions } from './transformers/filterByRefId'; export { ReduceTransformerOptions } from './transformers/reduce'; export { OrganizeFieldsTransformerOptions } from './transformers/organize'; export { createOrderFieldsComparer } from './transformers/order'; +export { transformDataFrame } from './transformDataFrame'; +export { + TransformerRegistyItem, + TransformerUIProps, + standardTransformersRegistry, +} from './standardTransformersRegistry'; diff --git a/packages/grafana-data/src/transformations/standardTransformersRegistry.ts b/packages/grafana-data/src/transformations/standardTransformersRegistry.ts new file mode 100644 index 00000000000..2bfd48b3693 --- /dev/null +++ b/packages/grafana-data/src/transformations/standardTransformersRegistry.ts @@ -0,0 +1,32 @@ +import React from 'react'; +import { DataFrame, DataTransformerInfo } from '../types'; +import { Registry, RegistryItem } from '../utils/Registry'; + +export interface TransformerUIProps { + /** + * Transformer configuration, persisted on panel's model + */ + options: T; + /** + * Pre-transform data rames + */ + input: DataFrame[]; + onChange: (options: T) => void; +} + +export interface TransformerRegistyItem extends RegistryItem { + /** + * Object describing transformer configuration + */ + transformation: DataTransformerInfo; + /** + * React component used as UI for the transformer + */ + editor: React.ComponentType>; +} + +/** + * Registry of transformation options that can be driven by + * stored configuration files. + */ +export const standardTransformersRegistry = new Registry>(); diff --git a/packages/grafana-data/src/transformations/transformDataFrame.ts b/packages/grafana-data/src/transformations/transformDataFrame.ts new file mode 100644 index 00000000000..058ca1163fe --- /dev/null +++ b/packages/grafana-data/src/transformations/transformDataFrame.ts @@ -0,0 +1,35 @@ +import { DataFrame, DataTransformerConfig } from '../types'; +import { standardTransformersRegistry } from './standardTransformersRegistry'; + +/** + * Apply configured transformations to the input data + */ +export function transformDataFrame(options: DataTransformerConfig[], data: DataFrame[]): DataFrame[] { + let processed = data; + for (const config of options) { + const info = standardTransformersRegistry.get(config.id); + + if (!info) { + return data; + } + + const transformer = info.transformation.transformer(config.options); + const after = transformer(processed); + + // Add a key to the metadata if the data changed + if (after && after !== processed) { + for (const series of after) { + if (!series.meta) { + series.meta = {}; + } + if (!series.meta.transformations) { + series.meta.transformations = [info.id]; + } else { + series.meta.transformations = [...series.meta.transformations, info.id]; + } + } + processed = after; + } + } + return processed; +} diff --git a/packages/grafana-data/src/transformations/transformers.test.ts b/packages/grafana-data/src/transformations/transformers.test.ts deleted file mode 100644 index 655587e2667..00000000000 --- a/packages/grafana-data/src/transformations/transformers.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DataTransformerID } from './transformers/ids'; -import { transformersRegistry } from './transformers'; -import { toDataFrame } from '../dataframe/processDataFrame'; -import { ReducerID } from './fieldReducer'; -import { DataFrameView } from '../dataframe/DataFrameView'; - -describe('Transformers', () => { - it('should load all transformeres', () => { - for (const name of Object.keys(DataTransformerID)) { - const calc = transformersRegistry.get(name); - expect(calc.id).toBe(name); - } - }); - - const seriesWithValues = toDataFrame({ - fields: [ - { name: 'A', values: [1, 2, 3, 4] }, // Numbers - { name: 'B', values: ['a', 'b', 'c', 'd'] }, // Strings - ], - }); - - it('should use fluent API', () => { - const results = transformersRegistry.reduce([seriesWithValues], { - reducers: [ReducerID.first], - }); - expect(results.length).toBe(1); - - const view = new DataFrameView(results[0]).toJSON(); - expect(view).toEqual([ - { Field: 'A', first: 1 }, // Row 0 - { Field: 'B', first: 'a' }, // Row 1 - ]); - }); -}); diff --git a/packages/grafana-data/src/transformations/transformers.ts b/packages/grafana-data/src/transformations/transformers.ts index cc575a0ad0b..f26826b517a 100644 --- a/packages/grafana-data/src/transformations/transformers.ts +++ b/packages/grafana-data/src/transformations/transformers.ts @@ -1,70 +1,15 @@ -import { DataFrame } from '../types/dataFrame'; -import { Registry } from '../utils/Registry'; -import { AppendOptions, appendTransformer } from './transformers/append'; -import { reduceTransformer, ReduceTransformerOptions } from './transformers/reduce'; +import { appendTransformer } from './transformers/append'; +import { reduceTransformer } from './transformers/reduce'; import { filterFieldsTransformer, filterFramesTransformer } from './transformers/filter'; -import { filterFieldsByNameTransformer, FilterFieldsByNameTransformerOptions } from './transformers/filterByName'; +import { filterFieldsByNameTransformer } from './transformers/filterByName'; import { noopTransformer } from './transformers/noop'; -import { DataTransformerConfig, DataTransformerInfo } from '../types/transformations'; import { filterFramesByRefIdTransformer } from './transformers/filterByRefId'; import { orderFieldsTransformer } from './transformers/order'; import { organizeFieldsTransformer } from './transformers/organize'; import { seriesToColumnsTransformer } from './transformers/seriesToColumns'; import { renameFieldsTransformer } from './transformers/rename'; -// Initalize the Registry - -/** - * Apply configured transformations to the input data - */ -export function transformDataFrame(options: DataTransformerConfig[], data: DataFrame[]): DataFrame[] { - let processed = data; - for (const config of options) { - const info = transformersRegistry.get(config.id); - const transformer = info.transformer(config.options); - const after = transformer(processed); - - // Add a key to the metadata if the data changed - if (after && after !== processed) { - for (const series of after) { - if (!series.meta) { - series.meta = {}; - } - if (!series.meta.transformations) { - series.meta.transformations = [info.id]; - } else { - series.meta.transformations = [...series.meta.transformations, info.id]; - } - } - processed = after; - } - } - return processed; -} - -/** - * Registry of transformation options that can be driven by - * stored configuration files. - */ -class TransformerRegistry extends Registry { - // ------------------------------------------------------------ - // Nacent options for more functional programming - // The API to these functions should change to match the actual - // needs of people trying to use it. - // filterFields|Frames is left off since it is likely easier to - // support with `frames.filter( f => {...} )` - // ------------------------------------------------------------ - - append(data: DataFrame[], options?: AppendOptions): DataFrame | undefined { - return appendTransformer.transformer(options || appendTransformer.defaultOptions)(data)[0]; - } - - reduce(data: DataFrame[], options: ReduceTransformerOptions): DataFrame[] { - return reduceTransformer.transformer(options)(data); - } -} - -export const transformersRegistry = new TransformerRegistry(() => [ +export const standardTransformers = { noopTransformer, filterFieldsTransformer, filterFieldsByNameTransformer, @@ -76,6 +21,4 @@ export const transformersRegistry = new TransformerRegistry(() => [ reduceTransformer, seriesToColumnsTransformer, renameFieldsTransformer, -]); - -export { ReduceTransformerOptions, FilterFieldsByNameTransformerOptions }; +}; diff --git a/packages/grafana-data/src/transformations/transformers/append.test.ts b/packages/grafana-data/src/transformations/transformers/append.test.ts index 6d92627dccd..1c2a07e3008 100644 --- a/packages/grafana-data/src/transformations/transformers/append.test.ts +++ b/packages/grafana-data/src/transformations/transformers/append.test.ts @@ -1,7 +1,8 @@ import { DataTransformerID } from './ids'; import { toDataFrame } from '../../dataframe/processDataFrame'; -import { transformDataFrame } from '../transformers'; -import { transformersRegistry } from '../transformers'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { appendTransformer } from './append'; +import { transformDataFrame } from '../transformDataFrame'; const seriesAB = toDataFrame({ columns: [{ text: 'A' }, { text: 'B' }], @@ -20,13 +21,14 @@ const seriesBC = toDataFrame({ }); describe('Append Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([appendTransformer]); + }); it('filters by include', () => { const cfg = { id: DataTransformerID.append, options: {}, }; - const x = transformersRegistry.get(DataTransformerID.append); - expect(x.id).toBe(cfg.id); const processed = transformDataFrame([cfg], [seriesAB, seriesBC])[0]; expect(processed.fields.length).toBe(3); diff --git a/packages/grafana-data/src/transformations/transformers/filter.test.ts b/packages/grafana-data/src/transformations/transformers/filter.test.ts index af8846674bc..5eb3991703b 100644 --- a/packages/grafana-data/src/transformations/transformers/filter.test.ts +++ b/packages/grafana-data/src/transformations/transformers/filter.test.ts @@ -2,7 +2,9 @@ import { FieldType } from '../../types/dataFrame'; import { DataTransformerID } from './ids'; import { toDataFrame } from '../../dataframe/processDataFrame'; import { FieldMatcherID } from '../matchers/ids'; -import { transformDataFrame } from '../transformers'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { filterFieldsTransformer } from './filter'; +import { transformDataFrame } from '../transformDataFrame'; export const simpleSeriesWithTypes = toDataFrame({ fields: [ @@ -14,6 +16,10 @@ export const simpleSeriesWithTypes = toDataFrame({ }); describe('Filter Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([filterFieldsTransformer]); + }); + it('filters by include', () => { const cfg = { id: DataTransformerID.filterFields, diff --git a/packages/grafana-data/src/transformations/transformers/filterByName.test.ts b/packages/grafana-data/src/transformations/transformers/filterByName.test.ts index ac764da977d..890c9e6a8b9 100644 --- a/packages/grafana-data/src/transformations/transformers/filterByName.test.ts +++ b/packages/grafana-data/src/transformations/transformers/filterByName.test.ts @@ -1,7 +1,10 @@ import { DataTransformerID } from './ids'; -import { transformDataFrame } from '../transformers'; import { toDataFrame } from '../../dataframe/processDataFrame'; import { FieldType } from '../../types/dataFrame'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { filterFieldsByNameTransformer } from './filterByName'; +import { filterFieldsTransformer } from './filter'; +import { transformDataFrame } from '../transformDataFrame'; export const seriesWithNamesToMatch = toDataFrame({ fields: [ @@ -13,6 +16,10 @@ export const seriesWithNamesToMatch = toDataFrame({ }); describe('filterByName transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([filterFieldsByNameTransformer, filterFieldsTransformer]); + }); + it('returns original series if no options provided', () => { const cfg = { id: DataTransformerID.filterFields, diff --git a/packages/grafana-data/src/transformations/transformers/filterByRefId.test.ts b/packages/grafana-data/src/transformations/transformers/filterByRefId.test.ts index 81e8d4a4766..0bec449d212 100644 --- a/packages/grafana-data/src/transformations/transformers/filterByRefId.test.ts +++ b/packages/grafana-data/src/transformations/transformers/filterByRefId.test.ts @@ -1,6 +1,8 @@ import { DataTransformerID } from './ids'; -import { transformDataFrame } from '../transformers'; import { toDataFrame } from '../../dataframe/processDataFrame'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { filterFramesByRefIdTransformer } from './filterByRefId'; +import { transformDataFrame } from '../transformDataFrame'; export const allSeries = [ toDataFrame({ @@ -18,6 +20,9 @@ export const allSeries = [ ]; describe('filterByRefId transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([filterFramesByRefIdTransformer]); + }); it('returns all series if no options provided', () => { const cfg = { id: DataTransformerID.filterByRefId, diff --git a/packages/grafana-data/src/transformations/transformers/order.test.ts b/packages/grafana-data/src/transformations/transformers/order.test.ts index 709b48957bf..de6ff8bc210 100644 --- a/packages/grafana-data/src/transformations/transformers/order.test.ts +++ b/packages/grafana-data/src/transformations/transformers/order.test.ts @@ -6,9 +6,13 @@ import { toDataFrame, transformDataFrame, } from '@grafana/data'; -import { OrderFieldsTransformerOptions } from './order'; +import { orderFieldsTransformer, OrderFieldsTransformerOptions } from './order'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; describe('Order Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([orderFieldsTransformer]); + }); describe('when consistent data is received', () => { const data = toDataFrame({ name: 'A', diff --git a/packages/grafana-data/src/transformations/transformers/organize.test.ts b/packages/grafana-data/src/transformations/transformers/organize.test.ts index 7ec62b4bcb2..215ffd58ae0 100644 --- a/packages/grafana-data/src/transformations/transformers/organize.test.ts +++ b/packages/grafana-data/src/transformations/transformers/organize.test.ts @@ -6,9 +6,14 @@ import { toDataFrame, transformDataFrame, } from '@grafana/data'; -import { OrganizeFieldsTransformerOptions } from './organize'; +import { organizeFieldsTransformer, OrganizeFieldsTransformerOptions } from './organize'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; describe('OrganizeFields Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([organizeFieldsTransformer]); + }); + describe('when consistent data is received', () => { const data = toDataFrame({ name: 'A', diff --git a/packages/grafana-data/src/transformations/transformers/reduce.test.ts b/packages/grafana-data/src/transformations/transformers/reduce.test.ts index 244f87dff8c..938bb6f7d20 100644 --- a/packages/grafana-data/src/transformations/transformers/reduce.test.ts +++ b/packages/grafana-data/src/transformations/transformers/reduce.test.ts @@ -1,7 +1,9 @@ import { ReducerID } from '../fieldReducer'; import { DataTransformerID } from './ids'; import { toDataFrame, toDataFrameDTO } from '../../dataframe/processDataFrame'; -import { transformDataFrame } from '../transformers'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; +import { reduceTransformer } from './reduce'; +import { transformDataFrame } from '../transformDataFrame'; const seriesWithValues = toDataFrame({ fields: [ @@ -11,6 +13,9 @@ const seriesWithValues = toDataFrame({ }); describe('Reducer Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([reduceTransformer]); + }); it('filters by include', () => { const cfg = { id: DataTransformerID.reduce, diff --git a/packages/grafana-data/src/transformations/transformers/rename.test.ts b/packages/grafana-data/src/transformations/transformers/rename.test.ts index 2d10f109c17..16d181a8d04 100644 --- a/packages/grafana-data/src/transformations/transformers/rename.test.ts +++ b/packages/grafana-data/src/transformations/transformers/rename.test.ts @@ -6,9 +6,14 @@ import { toDataFrame, transformDataFrame, } from '@grafana/data'; -import { RenameFieldsTransformerOptions } from './rename'; +import { RenameFieldsTransformerOptions, renameFieldsTransformer } from './rename'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; describe('Rename Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([renameFieldsTransformer]); + }); + describe('when consistent data is received', () => { const data = toDataFrame({ name: 'A', diff --git a/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts b/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts index 36f49b0487d..ba898945c7e 100644 --- a/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts +++ b/packages/grafana-data/src/transformations/transformers/seriesToColumns.test.ts @@ -6,9 +6,13 @@ import { toDataFrame, transformDataFrame, } from '@grafana/data'; -import { SeriesToColumnsOptions } from './seriesToColumns'; +import { SeriesToColumnsOptions, seriesToColumnsTransformer } from './seriesToColumns'; +import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; describe('SeriesToColumns Transformer', () => { + beforeAll(() => { + mockTransformationsRegistry([seriesToColumnsTransformer]); + }); const everySecondSeries = toDataFrame({ name: 'even', fields: [ diff --git a/packages/grafana-data/src/types/transformations.ts b/packages/grafana-data/src/types/transformations.ts index 6fab55410f5..d0198f59795 100644 --- a/packages/grafana-data/src/types/transformations.ts +++ b/packages/grafana-data/src/types/transformations.ts @@ -2,16 +2,26 @@ import { DataFrame, Field } from './dataFrame'; import { RegistryItemWithOptions } from '../utils/Registry'; /** - * Immutable data transformation + * Function that transform data frames (AKA transformer) */ export type DataTransformer = (data: DataFrame[]) => DataFrame[]; export interface DataTransformerInfo extends RegistryItemWithOptions { + /** + * Function that configures transformation and returns a transformer + * @param options + */ transformer: (options: TOptions) => DataTransformer; } export interface DataTransformerConfig { + /** + * Unique identifier of transformer + */ id: string; + /** + * Options to be passed to the transformer + */ options: TOptions; } diff --git a/packages/grafana-data/src/utils/tests/mockTransformationsRegistry.ts b/packages/grafana-data/src/utils/tests/mockTransformationsRegistry.ts new file mode 100644 index 00000000000..71eb42377e1 --- /dev/null +++ b/packages/grafana-data/src/utils/tests/mockTransformationsRegistry.ts @@ -0,0 +1,16 @@ +import { standardTransformersRegistry } from '../../transformations'; +import { DataTransformerInfo } from '../../types'; + +export const mockTransformationsRegistry = (transformers: Array>) => { + standardTransformersRegistry.setInit(() => { + return transformers.map(t => { + return { + id: t.id, + name: t.name, + transformation: t, + description: t.description, + editor: () => null, + }; + }); + }); +}; diff --git a/packages/grafana-ui/src/components/Button/Button.tsx b/packages/grafana-ui/src/components/Button/Button.tsx index a58a6409955..b16ea804492 100644 --- a/packages/grafana-ui/src/components/Button/Button.tsx +++ b/packages/grafana-ui/src/components/Button/Button.tsx @@ -25,15 +25,13 @@ const buttonVariantStyles = (from: string, to: string, textColor: string) => css const getPropertiesForVariant = (theme: GrafanaTheme, variant: ButtonVariant) => { switch (variant) { case 'secondary': - const from = selectThemeVariant({ light: theme.colors.gray7, dark: theme.colors.gray15 }, theme.type) as string; + const from = selectThemeVariant({ light: theme.colors.gray7, dark: theme.colors.gray10 }, theme.type) as string; const to = selectThemeVariant( { light: tinycolor(from) .darken(5) .toString(), - dark: tinycolor(from) - .lighten(4) - .toString(), + dark: theme.colors.gray05, }, theme.type ) as string; diff --git a/packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx b/packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx index 9b9561816fd..5c851508dee 100644 --- a/packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx +++ b/packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx @@ -1,6 +1,12 @@ import React, { useContext } from 'react'; -import { FilterFieldsByNameTransformerOptions, DataTransformerID, transformersRegistry, KeyValue } from '@grafana/data'; -import { TransformerUIProps, TransformerUIRegistyItem } from './types'; +import { + DataTransformerID, + FilterFieldsByNameTransformerOptions, + KeyValue, + standardTransformers, + TransformerRegistyItem, + TransformerUIProps, +} from '@grafana/data'; import { ThemeContext } from '../../themes/ThemeContext'; import { css, cx } from 'emotion'; import { InlineList } from '../List/InlineList'; @@ -154,10 +160,10 @@ const FilterPill: React.FC = ({ label, selected, onClick }) => ); }; -export const filterFieldsByNameTransformRegistryItem: TransformerUIRegistyItem = { +export const filterFieldsByNameTransformRegistryItem: TransformerRegistyItem = { id: DataTransformerID.filterFieldsByName, - component: FilterByNameTransformerEditor, - transformer: transformersRegistry.get(DataTransformerID.filterFieldsByName), + editor: FilterByNameTransformerEditor, + transformation: standardTransformers.filterFieldsByNameTransformer, name: 'Filter by name', - description: 'UI for filter by name transformation', + description: 'Filter fields by name', }; diff --git a/packages/grafana-ui/src/components/TransformersUI/FilterByRefIdTransformerEditor.tsx b/packages/grafana-ui/src/components/TransformersUI/FilterByRefIdTransformerEditor.tsx index 7f3e039f9ec..9ad8d7310b5 100644 --- a/packages/grafana-ui/src/components/TransformersUI/FilterByRefIdTransformerEditor.tsx +++ b/packages/grafana-ui/src/components/TransformersUI/FilterByRefIdTransformerEditor.tsx @@ -1,11 +1,12 @@ import React, { useContext } from 'react'; import { - FilterFramesByRefIdTransformerOptions, DataTransformerID, - transformersRegistry, + FilterFramesByRefIdTransformerOptions, KeyValue, + standardTransformers, + TransformerRegistyItem, + TransformerUIProps, } from '@grafana/data'; -import { TransformerUIProps, TransformerUIRegistyItem } from './types'; import { ThemeContext } from '../../themes/ThemeContext'; import { css, cx } from 'emotion'; import { InlineList } from '../List/InlineList'; @@ -159,10 +160,10 @@ const FilterPill: React.FC = ({ label, selected, onClick }) => ); }; -export const filterFramesByRefIdTransformRegistryItem: TransformerUIRegistyItem = { +export const filterFramesByRefIdTransformRegistryItem: TransformerRegistyItem = { id: DataTransformerID.filterByRefId, - component: FilterByRefIdTransformerEditor, - transformer: transformersRegistry.get(DataTransformerID.filterByRefId), + editor: FilterByRefIdTransformerEditor, + transformation: standardTransformers.filterFramesByRefIdTransformer, name: 'Filter by refId', description: 'Filter results by refId', }; diff --git a/packages/grafana-ui/src/components/TransformersUI/OrganizeFieldsTransformerEditor.tsx b/packages/grafana-ui/src/components/TransformersUI/OrganizeFieldsTransformerEditor.tsx index e63269cd598..7c0f89d0507 100644 --- a/packages/grafana-ui/src/components/TransformersUI/OrganizeFieldsTransformerEditor.tsx +++ b/packages/grafana-ui/src/components/TransformersUI/OrganizeFieldsTransformerEditor.tsx @@ -1,15 +1,16 @@ -import React, { useMemo, useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { css, cx } from 'emotion'; -import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd'; +import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd'; import { - DataTransformerID, - transformersRegistry, - DataFrame, - GrafanaTheme, createOrderFieldsComparer, + DataFrame, + DataTransformerID, + GrafanaTheme, OrganizeFieldsTransformerOptions, + standardTransformers, + TransformerRegistyItem, + TransformerUIProps, } from '@grafana/data'; -import { TransformerUIRegistyItem, TransformerUIProps } from './types'; import { stylesFactory, useTheme } from '../../themes'; import { Button } from '../Button/Button'; import { VerticalGroup } from '../Layout/Layout'; @@ -217,10 +218,10 @@ const fieldNamesFromInput = (input: DataFrame[]): string[] => { ); }; -export const organizeFieldsTransformRegistryItem: TransformerUIRegistyItem = { +export const organizeFieldsTransformRegistryItem: TransformerRegistyItem = { id: DataTransformerID.organize, - component: OrganizeFieldsTransformerEditor, - transformer: transformersRegistry.get(DataTransformerID.organize), + editor: OrganizeFieldsTransformerEditor, + transformation: standardTransformers.organizeFieldsTransformer, name: 'Organize fields', - description: 'UI for organizing fields', + description: 'Order, filter and rename fields', }; diff --git a/packages/grafana-ui/src/components/TransformersUI/ReduceTransformerEditor.tsx b/packages/grafana-ui/src/components/TransformersUI/ReduceTransformerEditor.tsx index 5b28d0643b5..d4fe1371e55 100644 --- a/packages/grafana-ui/src/components/TransformersUI/ReduceTransformerEditor.tsx +++ b/packages/grafana-ui/src/components/TransformersUI/ReduceTransformerEditor.tsx @@ -1,13 +1,18 @@ import React from 'react'; import { StatsPicker } from '../StatsPicker/StatsPicker'; -import { ReduceTransformerOptions, DataTransformerID, ReducerID, transformersRegistry } from '@grafana/data'; -import { TransformerUIRegistyItem, TransformerUIProps } from './types'; +import { + ReduceTransformerOptions, + DataTransformerID, + ReducerID, + standardTransformers, + TransformerRegistyItem, + TransformerUIProps, +} from '@grafana/data'; // TODO: Minimal implementation, needs some <3 export const ReduceTransformerEditor: React.FC> = ({ options, onChange, - input, }) => { return ( = { +export const reduceTransformRegistryItem: TransformerRegistyItem = { id: DataTransformerID.reduce, - component: ReduceTransformerEditor, - transformer: transformersRegistry.get(DataTransformerID.reduce), + editor: ReduceTransformerEditor, + transformation: standardTransformers.reduceTransformer, name: 'Reduce', - description: 'UI for reduce transformation', + description: 'Return a DataFrame with the reduction results', }; diff --git a/packages/grafana-ui/src/components/TransformersUI/transformers.ts b/packages/grafana-ui/src/components/TransformersUI/transformers.ts deleted file mode 100644 index 28780c3df11..00000000000 --- a/packages/grafana-ui/src/components/TransformersUI/transformers.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Registry } from '@grafana/data'; -import { reduceTransformRegistryItem } from './ReduceTransformerEditor'; -import { filterFieldsByNameTransformRegistryItem } from './FilterByNameTransformerEditor'; -import { filterFramesByRefIdTransformRegistryItem } from './FilterByRefIdTransformerEditor'; -import { TransformerUIRegistyItem } from './types'; -import { organizeFieldsTransformRegistryItem } from './OrganizeFieldsTransformerEditor'; - -export const transformersUIRegistry = new Registry>(() => { - return [ - reduceTransformRegistryItem, - filterFieldsByNameTransformRegistryItem, - filterFramesByRefIdTransformRegistryItem, - organizeFieldsTransformRegistryItem, - ]; -}); diff --git a/packages/grafana-ui/src/components/TransformersUI/types.ts b/packages/grafana-ui/src/components/TransformersUI/types.ts deleted file mode 100644 index de26d92bf0b..00000000000 --- a/packages/grafana-ui/src/components/TransformersUI/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { DataFrame, RegistryItem, DataTransformerInfo } from '@grafana/data'; - -export interface TransformerUIRegistyItem extends RegistryItem { - component: React.ComponentType>; - transformer: DataTransformerInfo; -} - -export interface TransformerUIProps { - // Transformer configuration, persisted on panel's model - options: T; - // Pre-transformation data frame - input: DataFrame[]; - onChange: (options: T) => void; -} diff --git a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx index 853bb8f894c..f54e14302b8 100644 --- a/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx +++ b/packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx @@ -4,6 +4,7 @@ import { SelectableValue } from '@grafana/data'; import { Button, ButtonVariant } from '../Button'; import { Select } from '../Select/Select'; import { FullWidthButtonContainer } from '../Button/FullWidthButtonContainer'; +import { ComponentSize } from '../../types/size'; interface ValuePickerProps { /** Label to display on the picker button */ @@ -14,20 +15,29 @@ interface ValuePickerProps { options: Array>; onChange: (value: SelectableValue) => void; variant?: ButtonVariant; + size?: ComponentSize; + isFullWidth?: boolean; } -export function ValuePicker({ label, icon, options, onChange, variant }: ValuePickerProps) { +export function ValuePicker({ + label, + icon, + options, + onChange, + variant, + size, + isFullWidth = true, +}: ValuePickerProps) { const [isPicking, setIsPicking] = useState(false); + const buttonEl = ( + + ); return ( <> - {!isPicking && ( - - - - )} + {!isPicking && (isFullWidth ? {buttonEl} : buttonEl)} {isPicking && ( - + ); }; @@ -83,7 +71,7 @@ export class TransformationsEditor extends React.PureComponent { {transformations.map((t, i) => { let editor; - const transformationUI = transformersUIRegistry.getIfExists(t.id); + const transformationUI = standardTransformersRegistry.getIfExists(t.id); if (!transformationUI) { return null; } @@ -92,8 +80,8 @@ export class TransformationsEditor extends React.PureComponent { const output = transformDataFrame(transformations.slice(i), input); if (transformationUI) { - editor = React.createElement(transformationUI.component, { - options: { ...transformationUI.transformer.defaultOptions, ...t.options }, + editor = React.createElement(transformationUI.editor, { + options: { ...transformationUI.transformation.defaultOptions, ...t.options }, input, onChange: (options: any) => { this.onTransformationChange(i, { @@ -130,9 +118,6 @@ export class TransformationsEditor extends React.PureComponent {

{this.renderTransformationEditors()} {this.renderTransformationSelector()} - );