import React, { useCallback, useMemo } from 'react'; import { css, cx } from 'emotion'; import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd'; import { createOrderFieldsComparer, DataFrame, DataTransformerID, GrafanaTheme, OrganizeFieldsTransformerOptions, standardTransformers, TransformerRegistyItem, TransformerUIProps, } from '@grafana/data'; import { stylesFactory, useTheme } from '../../themes'; import { Button } from '../Button/Button'; import { VerticalGroup } from '../Layout/Layout'; import { Input } from '../Input/Input'; interface OrganizeFieldsTransformerEditorProps extends TransformerUIProps {} const OrganizeFieldsTransformerEditor: React.FC = props => { const { options, input, onChange } = props; const { indexByName, excludeByName, renameByName } = options; const fieldNames = useMemo(() => fieldNamesFromInput(input), [input]); const orderedFieldNames = useMemo(() => orderFieldNamesByIndex(fieldNames, indexByName), [fieldNames, indexByName]); const onToggleVisibility = useCallback( (field: string, shouldExclude: boolean) => { onChange({ ...options, excludeByName: { ...excludeByName, [field]: shouldExclude, }, }); }, [onChange, excludeByName, indexByName] ); const onDragEnd = useCallback( (result: DropResult) => { if (!result || !result.destination) { return; } const startIndex = result.source.index; const endIndex = result.destination.index; if (startIndex === endIndex) { return; } onChange({ ...options, indexByName: reorderToIndex(fieldNames, startIndex, endIndex), }); }, [onChange, indexByName, excludeByName, fieldNames] ); const onRenameField = useCallback( (from: string, to: string) => { onChange({ ...options, renameByName: { ...options.renameByName, [from]: to, }, }); }, [onChange, fieldNames, renameByName] ); return ( {provided => (
{orderedFieldNames.map((fieldName, index) => { return ( ); })} {provided.placeholder}
)}
); }; interface DraggableFieldProps { fieldName: string; index: number; visible: boolean; onToggleVisibility: (fieldName: string, isVisible: boolean) => void; onRenameField: (from: string, to: string) => void; } const DraggableFieldName: React.FC = ({ fieldName, index, visible, onToggleVisibility, onRenameField, }) => { const theme = useTheme(); const styles = getFieldNameStyles(theme); return ( {provided => (
onRenameField(fieldName, event.currentTarget.value)} />
)}
); }; const getFieldNameStyles = stylesFactory((theme: GrafanaTheme) => ({ container: css` display: flex; align-items: center; margin-top: 8px; `, left: css` width: 35%; padding: 0 8px; border-radius: 3px; background-color: ${theme.colors.bg2}; `, right: css` width: 65%; margin-left: 8px; `, toggle: css` padding: 5px; margin: 0 5px; `, draggable: css` font-size: ${theme.typography.size.md}; opacity: 0.4; `, name: css` font-size: ${theme.typography.size.sm}; font-weight: ${theme.typography.weight.semibold}; `, })); const reorderToIndex = (fieldNames: string[], startIndex: number, endIndex: number) => { const result = Array.from(fieldNames); const [removed] = result.splice(startIndex, 1); result.splice(endIndex, 0, removed); return result.reduce((nameByIndex, fieldName, index) => { nameByIndex[fieldName] = index; return nameByIndex; }, {} as Record); }; const orderFieldNamesByIndex = (fieldNames: string[], indexByName: Record = {}): string[] => { if (!indexByName || Object.keys(indexByName).length === 0) { return fieldNames; } const comparer = createOrderFieldsComparer(indexByName); return fieldNames.sort(comparer); }; const fieldNamesFromInput = (input: DataFrame[]): string[] => { if (!Array.isArray(input)) { return [] as string[]; } return Object.keys( input.reduce((names, frame) => { if (!frame || !Array.isArray(frame.fields)) { return names; } return frame.fields.reduce((names, field) => { names[field.name] = null; return names; }, names); }, {} as Record) ); }; export const organizeFieldsTransformRegistryItem: TransformerRegistyItem = { id: DataTransformerID.organize, editor: OrganizeFieldsTransformerEditor, transformation: standardTransformers.organizeFieldsTransformer, name: 'Organize fields', description: 'Order, filter and rename fields', };