mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Transformations: Build help content for all standard transformers (#74052)
* baldm0mma/transformation_info_modal * baldm0mma/transformation_info_modal/ add getDisplayContent * baldm0mma/transformation_info_modal/ reamove OperationRowHelp * baldm0mma/transformation_info_modal/ update prepMarkdown * baldm0mma/transformation_help_modal/ add example mkdwn * baldm0mma/transformation_help_modal/ add examples anno * baldm0mma/transformation_info_modal/ add calFieldHelper * baldm0mma/transformation_info_modal/ remove file * baldm0mma/transformation_info_modal/ add CalculateFieldHelper * baldm0mma/transformation_info_modal/ add TransformationEditorHelperModal * baldm0mma/transformation_info_modal/ add getHelperContent * baldm0mma/transformation_info_modal/ move TransformationEditorHelperModal * baldm0mma/transformation_info_modal/ add ReactElement * baldm0mma/transformations_info_modal * baldm0mma/transformation_info_modal/ update props for TransformationEditorHelperModal * baldm0mma/transformation_info_modal/ test * test * baldm0mma/transformation_info_modal/ reset vscode auth * baldm0mma/transformation_info_modal/ update getHelperContent * baldm0mma/transformations_info_modal/ add items for rebuilding markdown to react component * test * test * baldm0mma/transformations_info_modal/ remove comment in TransformationOperationRow * test * baldm0mma/transformation_info_modal/ add element to typing * baldm0mma/transformation_info_modal/ update getHelperContent with help component * baldm0mma/transformation_info_modal/ update modal title * baldm0mma/transformation_info_modal/ move logic to tranforms * baldm0mma/transformation_info_modal/ remove unused comments * baldm0mma/transformation_info_modal/ update standard reg * baldm0mma/trfansformation_info_modal/ remove context styling * baldm0mma/transformation_info_modal/ add content for CalculateFieldHelper * baldm0mma/transformation_info_modal/ add ConcatenateHelper * baldm0mma/transformations_info_modal/ add ConcatenateHelper * baldm0mma/transformation_info_modal/ add ConfigFromQueryHelper * baldm0mma/transformations/info_modal/ add ConvertFieldTypeHelper * baldm0mma/transformation_info_modal/ add CreateHeatmapHelp * baldm0mma/transformation_info_modal/ add ExtractFieldsHelper * baldm0mma/transformation_info_modal/ add FilterFieldsByNameHelper * baldm0mma/transformation_info_modal/ add FilterFieldsByNameHelper * baldm0mma/transformation_info_modal/ add OperationRowHelp to parse markdown * baldm0mma/transformation_info_modal/ remove commented out markdown * baldm0mma/transformations_info_modal/ remove comment * baldm0mma/transformation_info_modal/ update configFromQueryTransformRegistryItem * baldm0mma/transformation_info_modal/ update ConcatenateHelper * baldm0mma/transformation_info_modal/ update ConvertFieldTypeHelper * baldm0mma/transformation_info_modal/ update ExtractFieldsHelper * baldm0mma/transformation_info_modal/ update FieldLookupHelper * baldm0mma/transformation_info_modal/ update TransformationEditorHelperModal with determineContentDisplay() * baldm0mma/transformation_info_modal/ add FilterByRefIdHelper * baldm0mma/transformation_info_modal/ add FilterByValueHelper * baldm0mma/transformation_info_modal/ update file ext * baldm0mma/transformation_info_modal/ add GroupByHelper * baldm0mma/transformation_info_modal/ add HistogramHelper * baldm0mma/transformation_info_modal/ add JoinByFieldHelper * baldm0mma/transformation_info_modal/ add JoinByLabelsHelper * baldm0mma/transformations_info_modal/ add LabelsToFieldsHelper * baldm0mma/transformation_info_modal/ add LimitHelper * baldm0mma/transformation_info_modal/ add MergeHelper * baldm0mma/transformation_info_modal/ add PartitionByValuesHelper * baldm0mma/transformation_info_modal/ add ReduceHelper * baldm0mma/transformation_info_modal/ add RenameByRegexHelper * baldm0mma/transformation_info_modal/ add SeriesToRowsHelper * baldm0mma/transformation_info_modal/ add SortByHelper * baldm0mma/transformations_info_modal/ add spatial * baldm0mma/transformation_info_modal/ update to markdown * baldm0mma/transformation_info_modal/ remove comments * baldm0mma/transformation_info_modal/ update boarder with theme * baldm0mma/transformation_info_modal/ add test suite * baldm0mma/transformation_info_modal/ update tests * baldm0mma/transformation_info_modal/ update test to run on all transformations * baldm0mma/transformation_info_modaol/ add TimeSeriesTableHelper * baldm0mma/transformation_info_modal/ update concatenateHelper * baldm0mma/transformation_info_modal/ update calculateFieldHelper * baldmomma/transformation_info_modal/ update naming * baldm0mma/transformation_info_modal/ update getLinkToDocs location * baldm0mma/transformation_info_modal/ update docs * baldm0mma/transformation_info_modal/ update language * baldm0mma/transformation_info_modal/ rename test * baldm0mma/transformation_info_modal/ update naming 2 * baldm0mma/transformation_info_modal/ update to helper * baldm0mma/transformation_info_modal/ update docs * Apply suggestions from @imatwawana Co-authored-by: Isabel <76437239+imatwawana@users.noreply.github.com> * baldm0mma/transformation_info_modal/ update convertFieldTypeHelper capitalization * Hack around with generating Markdown from transformations helpers (#75677) ```console $ cd docs $ make sources/panels-visualizations/query-transform-data/transform-data/index.md $ make docs ``` Browse to http://localhost:3003/docs/grafana/latest/panels-visualizations/query-transform-data/transform-data/ Signed-off-by: Jack Baldry <jack.baldry@grafana.com> * baldm0mma/transformation_info_modal/ add calculateFieldHelper * baldm0mma/transformation_info_modal/ update concatenate * baldm0mma/transformation_info_modal/ add fieldLookup * baldm0mma/transformation_info_modal/ add filterFieldsByName * baldm0mma/transformation_info_modal/ add joinByField * baldm0mma/transformation_info_modal/ update renameByRegex * baldm0mma/transformation_info_modal/ update getHelperContent * baldm0mma/transformation_info_modal/ update calculateFieldTransformRegistryItem * baldm0mma/transformation_info_modal/ update concatenateTransformRegistryItem * baldm0mma/transformation_info_modal/ update configFromDataTransformer * baldm0mma/transformation_info_modal/ update extractFieldsTransformRegistryItem * baldm0mma/transformation_info_modal/ update formatTimeTransformerRegistryItem * baldm0mma/transformation_info_modal/ update heatmapTransformRegistryItem * baldm0mma/transformation_info_modal/ update mergeTransformerRegistryItem * baldm0mma/transformation_info_modal/ update timeSeriesTableTransformRegistryItem * baldm0mma/transformation_info_modal/ update doc builder * baldm0mma/transformation_info_modal/ update docs * baldm0mma/transformation_info_modal/ remove console log * baldm0mma/transformation_info_modal/ update console log * baldm0mma/transformation_info_modal/ update gitignore * baldm0mma/transformation_info_modal/ update calculateField * baldm0mma/transformation_info_modal/ add links * baldm0mma/transformation_info_modal/ update template * baldm0mma/transformation_info_modal/ update template with images * baldm0mma/transformation_info_modal/ build markdown * baldm0mma/transformations_info_modal/update with links * baldm0mma/transformation_info_modal/ update links * baldm0mma/transformation_info_modal/ apdate FormatTimeTransfomerEditor * baldm0mma/transformation_indo_modal/ update HeatmapTransformerEditor * baldm0mma/transformation_indo_modal/ update ConfigFromQueryTransformerEditor * baldm0mma/transformation_indo_modal/ update CalculateFieldTransformerEditor * baldm0mma/transformation_indo_modal/ update ConcatenateTransformerEditor * baldm0mma/transformation_indo_modal/ update FilterByNameTransformerEditor * baldm0mma/transformation_indo_modal/ update FilterByRefIdTransformerEditor * baldm0mma/transformation_indo_modal/ update GroupByTransformerEditor * baldm0mma/transformation_indo_modal/ update GroupingToMatrixTransformerEditor get helper * baldm0mma/transformation_indo_modal/ update SeriesToFieldsTransformerEditor get helper * baldm0mma/transformation_indo_modal/ update LabelsAsFieldsTransformerEditor * baldm0mma/transformation_info_modal/ update MergeTransformerEditor * baldm0mma/transformation_info_modal/ update OrganizeFieldsTransformerEditor * baldm0mma/transformation_info_modal/ update ReduceTransformerEditor * baldm0mma/transformation_info_modal/ update RenameByRegexTransformerEditor * baldm0mma/transformation_info_modal/ update SeriesToRowsTransformerEditor * baldm0mma/transformation_info_modal/ update SortByTransformerEditor * baldm0mma/transformation_info_modal/ update extractFieldsTransformerEditor * baldm0mma/transformation_info_modal/ update FilterByValueTransformerEditor * baldm0mma/transformation_info_modal/ update JoinByLabelsTransformerEditor * baldm0mma/transformation_info_modal/ update FieldLookupTransformerEditor * baldm0mma/transformation_info_modal/ update PartitionByValuesEditor * baldm0mma/transformation_info_modal/ update PrepareTimeSeriesEditor * baldm0mma/transformation_info_modal/ update RowsToFieldsTransformerEditor * baldm0mma/transformation_info_modal/ update spatialTransformRegistryItem * baldm0mma/transformation_info_modal/ update timeSeriesTableTransformRegistryItem * baldm0mma/transformation_info_modal/ update to helperDocs * baldm0mma/transformation_info_modal/ update built markdown * baldm0mma/transformation_info_modal/ run prettier * baldm0mma/transformation_info_modal/ update comments in getTransformationContent * baldm0mma/transformation_info_modal/ add removeMarkdownAnchorLinks * baldm0mma/transformation_info_modal/ update annos in getTransformationContent * baldm0mma/transformation_info_modal/ add requisite url prefix to markdown images * baldm0mma/transformation_info_modal/ add cleanMarkdownOfUnwantedSyntax * baldm0mma/transformation_info_modal/ update annos in content.ts * baldm0mma/transformation_info_modal/ update e2e tests with always-visiable trabnsformation * baldm0mma/transformation_info_modal/ remove note * baldm0mma/transformation_info_modal/ add annotation in getTransformationContent * baldm0mma/transformation_info_modal/ update e2e test naming --------- Signed-off-by: Jack Baldry <jack.baldry@grafana.com> Co-authored-by: Isabel <76437239+imatwawana@users.noreply.github.com> Co-authored-by: Jack Baldry <jack.baldry@grafana.com>
This commit is contained in:
parent
30f2ab07f5
commit
a99485ba33
@ -479,7 +479,7 @@ The result from using the regular expression 'prod.\*' would be:
|
||||
| 2023-03-04 23:56:23 | 22.2 | 20.2 |
|
||||
| 2023-03-04 23:56:23 | 22.1 | 20.1 |
|
||||
|
||||
The regular expression can include an interpolated dashboard variable by using the ${$variableName} syntax.
|
||||
The regular expression can include an interpolated dashboard variable by using the ${variableName} syntax.
|
||||
|
||||
#### Manually select included fields
|
||||
|
||||
|
@ -39,7 +39,7 @@ describe('Panel edit tests', () => {
|
||||
e2e.components.Tab.active().within((li: JQuery<HTMLLIElement>) => {
|
||||
expect(li.text()).equals('Transform data0'); // there's no transform so therefore Transform + 0
|
||||
});
|
||||
e2e.components.Transforms.card('Merge').scrollIntoView().should('be.visible');
|
||||
e2e.components.Transforms.card('Merge series/tables').scrollIntoView().should('be.visible');
|
||||
e2e.components.QueryTab.content().should('not.exist');
|
||||
e2e.components.AlertTab.content().should('not.exist');
|
||||
e2e.components.PanelAlertTabContent.content().should('not.exist');
|
||||
|
@ -8,19 +8,22 @@ export interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode;
|
||||
markdown?: string;
|
||||
onRemove?: () => void;
|
||||
styleOverrides?: { [key: string]: string };
|
||||
}
|
||||
|
||||
export const OperationRowHelp = React.memo(
|
||||
React.forwardRef<HTMLDivElement, Props>(({ className, children, markdown, onRemove, ...otherProps }, ref) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
React.forwardRef<HTMLDivElement, Props>(
|
||||
({ className, children, markdown, styleOverrides, onRemove, ...otherProps }, ref) => {
|
||||
const styles = useStyles2((theme) => getStyles(theme, styleOverrides?.borderTop));
|
||||
|
||||
return (
|
||||
<div className={cx(styles.wrapper, className)} {...otherProps} ref={ref}>
|
||||
{markdown && markdownHelper(markdown)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
return (
|
||||
<div className={cx(styles.wrapper, className)} {...otherProps} ref={ref}>
|
||||
{markdown && markdownHelper(markdown)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
function markdownHelper(markdown: string) {
|
||||
@ -30,14 +33,16 @@ function markdownHelper(markdown: string) {
|
||||
|
||||
OperationRowHelp.displayName = 'OperationRowHelp';
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
const getStyles = (theme: GrafanaTheme2, borderTop?: string) => {
|
||||
const borderRadius = theme.shape.radius.default;
|
||||
|
||||
const themeBackgroundColor = theme.colors.background.secondary;
|
||||
|
||||
return {
|
||||
wrapper: css`
|
||||
padding: ${theme.spacing(2)};
|
||||
border: 2px solid ${theme.colors.background.secondary};
|
||||
border-top: none;
|
||||
border: 2px solid ${themeBackgroundColor};
|
||||
border-top: ${borderTop ? borderTop + themeBackgroundColor : 'none'};
|
||||
border-radius: 0 0 ${borderRadius} ${borderRadius};
|
||||
position: relative;
|
||||
top: -4px;
|
||||
|
@ -0,0 +1,93 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import { TransformerRegistryItem } from '@grafana/data';
|
||||
import { getStandardTransformers } from 'app/features/transformers/standardTransformers';
|
||||
|
||||
import { TransformationEditorHelperModal } from './TransformationEditorHelperModal';
|
||||
|
||||
// Mock the onCloseClick function
|
||||
const mockOnCloseClick = jest.fn();
|
||||
|
||||
const standardTransformers: Array<TransformerRegistryItem<null>> = getStandardTransformers();
|
||||
|
||||
const singleTestTransformer: TransformerRegistryItem<null> = standardTransformers[0];
|
||||
|
||||
describe('TransformationEditorHelperModal', () => {
|
||||
it('renders the modal with the correct title and content', () => {
|
||||
// Test each transformer
|
||||
standardTransformers.forEach((transformer) => {
|
||||
const { unmount } = render(
|
||||
<TransformationEditorHelperModal isOpen={true} onCloseClick={mockOnCloseClick} transformer={transformer} />
|
||||
);
|
||||
|
||||
// Check if the modal title is rendered with the correct text
|
||||
expect(screen.getByText(`Transformation help - ${transformer.transformation.name}`)).toBeInTheDocument();
|
||||
|
||||
// Unmount the component to clean up
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it('calls onCloseClick when the modal is dismissed', () => {
|
||||
render(
|
||||
<TransformationEditorHelperModal
|
||||
isOpen={true}
|
||||
onCloseClick={mockOnCloseClick}
|
||||
transformer={singleTestTransformer}
|
||||
/>
|
||||
);
|
||||
|
||||
// Find and click the modal's close button
|
||||
const closeButton = screen.getByRole('button', { name: 'Close' });
|
||||
fireEvent.click(closeButton);
|
||||
|
||||
// Ensure that the onCloseClick function was called with the correct argument
|
||||
expect(mockOnCloseClick).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('does not render when isOpen is false', () => {
|
||||
render(
|
||||
<TransformationEditorHelperModal
|
||||
isOpen={false}
|
||||
onCloseClick={mockOnCloseClick}
|
||||
transformer={singleTestTransformer}
|
||||
/>
|
||||
);
|
||||
|
||||
// Ensure that the modal is not rendered
|
||||
expect(screen.queryByText(`Transformation help - ${singleTestTransformer.name}`)).toBeNull();
|
||||
});
|
||||
|
||||
it('renders a default message when help content is not provided', () => {
|
||||
const transformerWithoutHelp = { ...singleTestTransformer, help: undefined };
|
||||
|
||||
render(
|
||||
<TransformationEditorHelperModal
|
||||
isOpen={true}
|
||||
onCloseClick={mockOnCloseClick}
|
||||
transformer={transformerWithoutHelp}
|
||||
/>
|
||||
);
|
||||
|
||||
// Check if the default message is rendered when help content is not provided
|
||||
expect(screen.getByText('transformation documentation')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders with custom help content when provided', () => {
|
||||
const customHelpContent = 'Custom help content for testing';
|
||||
|
||||
const transformerWithCustomHelp = { ...singleTestTransformer, help: customHelpContent };
|
||||
|
||||
render(
|
||||
<TransformationEditorHelperModal
|
||||
isOpen={true}
|
||||
onCloseClick={mockOnCloseClick}
|
||||
transformer={transformerWithCustomHelp}
|
||||
/>
|
||||
);
|
||||
|
||||
// Check if the custom help content is rendered
|
||||
expect(screen.getByText(customHelpContent)).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
import { TransformerRegistryItem } from '@grafana/data';
|
||||
import { Modal } from '@grafana/ui';
|
||||
import { OperationRowHelp } from 'app/core/components/QueryOperationRow/OperationRowHelp';
|
||||
|
||||
import { getLinkToDocs } from '../../../transformers/docs/content';
|
||||
|
||||
interface TransformationEditorHelperModalProps {
|
||||
isOpen: boolean;
|
||||
onCloseClick: (value: boolean) => void;
|
||||
transformer: TransformerRegistryItem<null>;
|
||||
}
|
||||
|
||||
export const TransformationEditorHelperModal = ({
|
||||
isOpen,
|
||||
onCloseClick,
|
||||
transformer,
|
||||
}: TransformationEditorHelperModalProps) => {
|
||||
const {
|
||||
transformation: { name },
|
||||
help,
|
||||
} = transformer;
|
||||
|
||||
const helpContent = help ? help : getLinkToDocs();
|
||||
|
||||
const helpTitle = `Transformation help - ${name}`;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={helpTitle}
|
||||
isOpen={isOpen}
|
||||
onClickBackdrop={() => onCloseClick(false)}
|
||||
onDismiss={() => onCloseClick(false)}
|
||||
>
|
||||
<OperationRowHelp markdown={helpContent} styleOverrides={{ borderTop: '2px solid' }} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
@ -4,7 +4,6 @@ import { useToggle } from 'react-use';
|
||||
import { DataFrame, DataTransformerConfig, TransformerRegistryItem, FrameMatcherID } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { ConfirmModal } from '@grafana/ui';
|
||||
import { OperationRowHelp } from 'app/core/components/QueryOperationRow/OperationRowHelp';
|
||||
import {
|
||||
QueryOperationAction,
|
||||
QueryOperationToggleAction,
|
||||
@ -14,6 +13,7 @@ import config from 'app/core/config';
|
||||
import { PluginStateInfo } from 'app/features/plugins/components/PluginStateInfo';
|
||||
|
||||
import { TransformationEditor } from './TransformationEditor';
|
||||
import { TransformationEditorHelperModal } from './TransformationEditorHelperModal';
|
||||
import { TransformationFilter } from './TransformationFilter';
|
||||
import { TransformationsEditorTransformation } from './types';
|
||||
|
||||
@ -54,16 +54,6 @@ export const TransformationOperationRow = ({
|
||||
[onChange, configs]
|
||||
);
|
||||
|
||||
const toggleExpand = useCallback(() => {
|
||||
if (showHelp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We return `undefined` here since the QueryOperationRow component ignores an `undefined` value for the `isOpen` prop.
|
||||
// If we returned `false` here, the row would be collapsed when the user toggles off `showHelp`, which is not what we want.
|
||||
return undefined;
|
||||
}, [showHelp]);
|
||||
|
||||
// Adds or removes the frame filter
|
||||
const toggleFilter = useCallback(() => {
|
||||
let current = { ...configs[index].transformation };
|
||||
@ -106,8 +96,8 @@ export const TransformationOperationRow = ({
|
||||
title="Show transform help"
|
||||
icon="info-circle"
|
||||
// `instrumentToggleCallback` expects a function that takes a MouseEvent, is unused in the state setter. Instead, we simply toggle the state.
|
||||
onClick={instrumentToggleCallback((_e) => toggleShowHelp(!showHelp), 'help', showHelp)}
|
||||
active={!!showHelp}
|
||||
onClick={instrumentToggleCallback(toggleShowHelp, 'help', showHelp)}
|
||||
active={showHelp}
|
||||
/>
|
||||
{showFilter && (
|
||||
<QueryOperationToggleAction
|
||||
@ -153,46 +143,33 @@ export const TransformationOperationRow = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<QueryOperationRow
|
||||
id={id}
|
||||
index={index}
|
||||
title={`${index + 1} - ${uiConfig.name}`}
|
||||
draggable
|
||||
actions={renderActions}
|
||||
disabled={disabled}
|
||||
isOpen={toggleExpand()}
|
||||
// Assure that showHelp is untoggled when the row becomes collapsed.
|
||||
onClose={() => toggleShowHelp(false)}
|
||||
expanderMessages={{
|
||||
close: 'Collapse transformation row',
|
||||
open: 'Expand transformation row',
|
||||
}}
|
||||
>
|
||||
{showHelp && <OperationRowHelp markdown={prepMarkdown(uiConfig)} />}
|
||||
{filter && (
|
||||
<TransformationFilter index={index} config={configs[index].transformation} data={data} onChange={onChange} />
|
||||
)}
|
||||
<TransformationEditor
|
||||
debugMode={showDebug}
|
||||
<>
|
||||
<QueryOperationRow
|
||||
id={id}
|
||||
index={index}
|
||||
data={data}
|
||||
configs={configs}
|
||||
uiConfig={uiConfig}
|
||||
onChange={onChange}
|
||||
toggleShowDebug={toggleShowDebug}
|
||||
/>
|
||||
</QueryOperationRow>
|
||||
title={`${index + 1} - ${uiConfig.name}`}
|
||||
draggable
|
||||
actions={renderActions}
|
||||
disabled={disabled}
|
||||
expanderMessages={{
|
||||
close: 'Collapse transformation row',
|
||||
open: 'Expand transformation row',
|
||||
}}
|
||||
>
|
||||
{filter && (
|
||||
<TransformationFilter index={index} config={configs[index].transformation} data={data} onChange={onChange} />
|
||||
)}
|
||||
<TransformationEditor
|
||||
debugMode={showDebug}
|
||||
index={index}
|
||||
data={data}
|
||||
configs={configs}
|
||||
uiConfig={uiConfig}
|
||||
onChange={onChange}
|
||||
toggleShowDebug={toggleShowDebug}
|
||||
/>
|
||||
</QueryOperationRow>
|
||||
<TransformationEditorHelperModal transformer={uiConfig} isOpen={showHelp} onCloseClick={toggleShowHelp} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function prepMarkdown(uiConfig: TransformerRegistryItem<null>) {
|
||||
let helpMarkdown = uiConfig.help ?? uiConfig.description;
|
||||
|
||||
return `
|
||||
${helpMarkdown}
|
||||
|
||||
Go the <a href="https://grafana.com/docs/grafana/latest/panels/transformations/?utm_source=grafana" target="_blank" rel="noreferrer">
|
||||
transformation documentation
|
||||
</a> for more.
|
||||
`;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ export const TransformationOperationRows = ({
|
||||
<>
|
||||
{configs.map((t, i) => {
|
||||
const uiConfig = standardTransformersRegistry.getIfExists(t.transformation.id);
|
||||
|
||||
if (!uiConfig) {
|
||||
return null;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import {
|
||||
} from '@grafana/data/src/transformations/transformers/filterByValue';
|
||||
import { Button, RadioButtonGroup, InlineField, Box } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { DataFrameFieldsInfo, FilterByValueFilterEditor } from './FilterByValueFilterEditor';
|
||||
|
||||
const filterTypes: Array<SelectableValue<FilterByValueType>> = [
|
||||
@ -135,6 +137,7 @@ export const filterByValueTransformRegistryItem: TransformerRegistryItem<FilterB
|
||||
description:
|
||||
'Removes rows of the query results using user-defined filters. This is useful if you can not filter your data in the data source.',
|
||||
categories: new Set([TransformerCategory.Filter]),
|
||||
help: getTransformationContent(DataTransformerID.filterByValue).helperDocs,
|
||||
};
|
||||
|
||||
const useFieldsInfo = (data: DataFrame[]): DataFrameFieldsInfo => {
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
TransformerCategory,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { getDefaultOptions, getTransformerOptionPane } from '../spatial/optionsHelper';
|
||||
|
||||
import { addHeatmapCalculationOptions } from './editor/helper';
|
||||
@ -49,4 +50,5 @@ export const heatmapTransformRegistryItem: TransformerRegistryItem<HeatmapTransf
|
||||
description: heatmapTransformer.description,
|
||||
state: PluginState.alpha,
|
||||
categories: new Set([TransformerCategory.CreateNewVisualization]),
|
||||
help: getTransformationContent(heatmapTransformer.id).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { fieldMatchersUI, InlineField, InlineFieldRow, Select, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { FieldToConfigMappingEditor } from '../fieldToConfigMapping/FieldToConfigMappingEditor';
|
||||
|
||||
import { configFromDataTransformer, ConfigFromQueryTransformOptions } from './configFromQuery';
|
||||
@ -95,73 +96,7 @@ export const configFromQueryTransformRegistryItem: TransformerRegistryItem<Confi
|
||||
description: configFromDataTransformer.description,
|
||||
state: PluginState.beta,
|
||||
categories: new Set([TransformerCategory.CalculateNewFields]),
|
||||
help: `
|
||||
### Use cases
|
||||
|
||||
This transformation allows you select one query and from it extract standard options such as
|
||||
**Min**, **Max**, **Unit**, and **Thresholds** and apply them to other query results.
|
||||
This enables dynamic query driven visualization configuration.
|
||||
|
||||
### Options
|
||||
|
||||
- **Config query**: Selet the query that returns the data you want to use as configuration.
|
||||
- **Apply to**: Select what fields or series to apply the configuration to.
|
||||
- **Apply to options**: Usually a field type or field name regex depending on what option you selected in **Apply to**.
|
||||
|
||||
### Field mapping table
|
||||
|
||||
Below the configuration listed above you will find the field table. Here all fields found in the data returned by the config query will be listed along with a **Use as** and **Select** option. This table gives you control over what field should be mapped to which config property and if there are multiple rows which value to select.
|
||||
|
||||
## Example
|
||||
|
||||
Input[0] (From query: A, name: ServerA)
|
||||
|
||||
| Time | Value |
|
||||
| ------------- | ----- |
|
||||
| 1626178119127 | 10 |
|
||||
| 1626178119129 | 30 |
|
||||
|
||||
Input[1] (From query: B)
|
||||
|
||||
| Time | Value |
|
||||
| ------------- | ----- |
|
||||
| 1626178119127 | 100 |
|
||||
| 1626178119129 | 100 |
|
||||
|
||||
Output (Same as Input[0] but now with config on the Value field)
|
||||
|
||||
| Time | Value (config: Max=100) |
|
||||
| ------------- | ----------------------- |
|
||||
| 1626178119127 | 10 |
|
||||
| 1626178119129 | 30 |
|
||||
|
||||
Each row in the source data becomes a separate field. Each field now also has a maximum
|
||||
configuration option set. Options such as **min**, **max**, **unit**, and **thresholds** are all part of field configuration, and if they are set like this, they will be used by the visualization instead of any options that are manually configured.
|
||||
in the panel editor options pane.
|
||||
|
||||
## Value mappings
|
||||
|
||||
You can also transform a query result into value mappings. This is is a bit different because every
|
||||
row in the configuration query result is used to define a single value mapping row. See the following example.
|
||||
|
||||
Config query result:
|
||||
|
||||
| Value | Text | Color |
|
||||
| ----- | ------ | ----- |
|
||||
| L | Low | blue |
|
||||
| M | Medium | green |
|
||||
| H | High | red |
|
||||
|
||||
In the field mapping specify:
|
||||
|
||||
| Field | Use as | Select |
|
||||
| ----- | ----------------------- | ---------- |
|
||||
| Value | Value mappings / Value | All values |
|
||||
| Text | Value mappings / Text | All values |
|
||||
| Color | Value mappings / Ciolor | All values |
|
||||
|
||||
Grafana will build the value mappings from you query result and apply it the the real data query results. You should see values being mapped and colored according to the config query results.
|
||||
`,
|
||||
help: getTransformationContent(configFromDataTransformer.id).helperDocs,
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
|
@ -83,7 +83,7 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/add-field-from-calc-stat-example-7-0.png',
|
||||
imageRenderType,
|
||||
this.name
|
||||
'Add field from calculation'
|
||||
)}
|
||||
`;
|
||||
},
|
||||
@ -336,7 +336,7 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/filter-by-query-stat-example-7-0.png',
|
||||
imageRenderType,
|
||||
this.name
|
||||
'Filter data by query refId'
|
||||
)}
|
||||
`;
|
||||
},
|
||||
@ -440,7 +440,7 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
| 2023-03-04 23:56:23 | 22.2 | 20.2 |
|
||||
| 2023-03-04 23:56:23 | 22.1 | 20.1 |
|
||||
|
||||
The regular expression can include an interpolated dashboard variable by using the \${$${'variableName'}} syntax.
|
||||
The regular expression can include an interpolated dashboard variable by using the \${${'variableName'}} syntax.
|
||||
|
||||
#### Manually select included fields
|
||||
|
||||
@ -453,7 +453,8 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/filter-name-table-before-7-0.png',
|
||||
imageRenderType,
|
||||
this.name + 1
|
||||
// Distinguish alt text for multiple images by appending a number.
|
||||
'Filter fields by name' + 1
|
||||
)}
|
||||
|
||||
Here's the table after we applied the transformation to remove the Min field.
|
||||
@ -461,7 +462,7 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/filter-name-table-after-7-0.png',
|
||||
imageRenderType,
|
||||
this.name + 2
|
||||
'Filter fields by name' + 2
|
||||
)}
|
||||
|
||||
Here is the same query using a Stat visualization.
|
||||
@ -469,7 +470,7 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/filter-name-stat-after-7-0.png',
|
||||
imageRenderType,
|
||||
this.name + 3
|
||||
'Filter fields by name' + 3
|
||||
)}
|
||||
`;
|
||||
},
|
||||
@ -742,11 +743,19 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
|
||||
In the following example, a template query displays time series data from multiple servers in a table visualization. The results of only one query can be viewed at a time.
|
||||
|
||||
${buildImageContent('/static/img/docs/transformations/join-fields-before-7-0.png', imageRenderType, this.name + 1)}
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/join-fields-before-7-0.png',
|
||||
imageRenderType,
|
||||
'Join by field' + 1
|
||||
)}
|
||||
|
||||
I applied a transformation to join the query results using the time field. Now I can run calculations, combine, and organize the results in this new table.
|
||||
|
||||
${buildImageContent('/static/img/docs/transformations/join-fields-after-7-0.png', imageRenderType, this.name + 2)}
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/join-fields-after-7-0.png',
|
||||
imageRenderType,
|
||||
'Join by field' + 2
|
||||
)}
|
||||
`;
|
||||
},
|
||||
},
|
||||
@ -1071,12 +1080,16 @@ export const transformationDocsContent: TransformationDocsContentType = {
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/rename-by-regex-before-7-3.png',
|
||||
imageRenderType,
|
||||
this.name + 1
|
||||
'Rename by regex' + 1
|
||||
)}
|
||||
|
||||
With the transformation applied, you can see we are left with just the remainder of the string.
|
||||
|
||||
${buildImageContent('/static/img/docs/transformations/rename-by-regex-after-7-3.png', imageRenderType, this.name + 1)}
|
||||
${buildImageContent(
|
||||
'/static/img/docs/transformations/rename-by-regex-after-7-3.png',
|
||||
imageRenderType,
|
||||
'Rename by regex' + 2
|
||||
)}
|
||||
`;
|
||||
},
|
||||
},
|
||||
@ -1240,5 +1253,5 @@ function buildImageContent(source: string, imageRenderType: ImageRenderType, ima
|
||||
? // This will build a Hugo Shortcode "figure" image template, which shares the same default class and max-width.
|
||||
`{{< figure src="${source}" class="docs-image--no-shadow" max-width= "1100px" >}}`
|
||||
: // This will build generic Markdown image syntax for UI rendering.
|
||||
``;
|
||||
``;
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
import { transformationDocsContent, getLinkToDocs, ImageRenderType } from './content';
|
||||
|
||||
export function getTransformationContent(id: string): { name: string; helperDocs: string } {
|
||||
if (id in transformationDocsContent) {
|
||||
const { name, getHelperDocs, links } = transformationDocsContent[id];
|
||||
|
||||
const helperDocs = getHelperDocs(ImageRenderType.UIImage);
|
||||
|
||||
const cleansedMarkdown = cleanMarkdownOfUnwantedSyntax(helperDocs);
|
||||
|
||||
// NOTE: string interpolation whitespace/indentation formatting is intentional.
|
||||
if (links?.length) {
|
||||
const renderedLinks = links
|
||||
.map((link) => {
|
||||
return `
|
||||
Or visit <a href="${link.url}" target="_blank">${link.title}</a>\n
|
||||
`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
// If external links exist, build and add them to the returned documentation.
|
||||
return {
|
||||
name,
|
||||
helperDocs: `
|
||||
${cleansedMarkdown}
|
||||
${getLinkToDocs()}
|
||||
${renderedLinks}
|
||||
`,
|
||||
};
|
||||
}
|
||||
|
||||
// If NO external links exist, simply return the basic documentation.
|
||||
return {
|
||||
name,
|
||||
helperDocs: `
|
||||
${cleansedMarkdown}
|
||||
${getLinkToDocs()}
|
||||
`,
|
||||
};
|
||||
}
|
||||
|
||||
// If the transformation has no documentation, return an external link to the online documentation.
|
||||
return {
|
||||
name: 'No documentation found',
|
||||
helperDocs: getLinkToDocs(),
|
||||
};
|
||||
}
|
||||
|
||||
const cleanMarkdownOfUnwantedSyntax = (markdown: string) => {
|
||||
// Remove anchor links: [text](#link)
|
||||
const markdownWithoutAnchorLinks = markdown.replace(/\[(.*?)\]\(#.*?\)/g, '$1');
|
||||
|
||||
// Remove shortcode syntax: [text][]
|
||||
const markdownWithoutShortcodeSyntax = markdownWithoutAnchorLinks.replace(/\[[^\]]*\]\[\]/g, '');
|
||||
|
||||
return markdownWithoutShortcodeSyntax;
|
||||
};
|
@ -49,6 +49,8 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
interface CalculateFieldTransformerEditorProps extends TransformerUIProps<CalculateFieldTransformerOptions> {}
|
||||
|
||||
interface CalculateFieldTransformerEditorState {
|
||||
@ -668,7 +670,8 @@ export const calculateFieldTransformRegistryItem: TransformerRegistryItem<Calcul
|
||||
id: DataTransformerID.calculateField,
|
||||
editor: CalculateFieldTransformerEditor,
|
||||
transformation: standardTransformers.calculateFieldTransformer,
|
||||
name: 'Add field from calculation',
|
||||
name: standardTransformers.calculateFieldTransformer.name,
|
||||
description: 'Use the row values to calculate a new field.',
|
||||
categories: new Set([TransformerCategory.CalculateNewFields]),
|
||||
help: getTransformationContent(DataTransformerID.calculateField).helperDocs,
|
||||
};
|
||||
|
@ -14,6 +14,8 @@ import {
|
||||
} from '@grafana/data/src/transformations/transformers/concat';
|
||||
import { Input, Select } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
interface ConcatenateTransformerEditorProps extends TransformerUIProps<ConcatenateTransformerOptions> {}
|
||||
|
||||
const nameModes: Array<SelectableValue<ConcatenateFrameNameMode>> = [
|
||||
@ -88,8 +90,9 @@ export const concatenateTransformRegistryItem: TransformerRegistryItem<Concatena
|
||||
id: DataTransformerID.concatenate,
|
||||
editor: ConcatenateTransformerEditor,
|
||||
transformation: standardTransformers.concatenateTransformer,
|
||||
name: 'Concatenate fields',
|
||||
name: standardTransformers.concatenateTransformer.name,
|
||||
description:
|
||||
'Combine all fields into a single frame. Values will be appended with undefined values if not the same length.',
|
||||
categories: new Set([TransformerCategory.Combine]),
|
||||
help: getTransformationContent(DataTransformerID.concatenate).helperDocs,
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ import { allFieldTypeIconOptions } from '@grafana/ui/src/components/MatchersUI/F
|
||||
import { hasAlphaPanels } from 'app/core/config';
|
||||
import { findField } from 'app/features/dimensions';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { getTimezoneOptions } from '../utils';
|
||||
|
||||
const fieldNamePickerSettings = {
|
||||
@ -204,4 +205,5 @@ export const convertFieldTypeTransformRegistryItem: TransformerRegistryItem<Conv
|
||||
name: standardTransformers.convertFieldTypeTransformer.name,
|
||||
description: standardTransformers.convertFieldTypeTransformer.description,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.convertFieldType).helperDocs,
|
||||
};
|
||||
|
@ -15,6 +15,8 @@ import { FilterFieldsByNameTransformerOptions } from '@grafana/data/src/transfor
|
||||
import { getTemplateSrv } from '@grafana/runtime/src/services';
|
||||
import { Input, FilterPill, InlineFieldRow, InlineField, InlineSwitch, Select } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
interface FilterByNameTransformerEditorProps extends TransformerUIProps<FilterFieldsByNameTransformerOptions> {}
|
||||
|
||||
interface FilterByNameTransformerEditorState {
|
||||
@ -251,7 +253,8 @@ export const filterFieldsByNameTransformRegistryItem: TransformerRegistryItem<Fi
|
||||
id: DataTransformerID.filterFieldsByName,
|
||||
editor: FilterByNameTransformerEditor,
|
||||
transformation: standardTransformers.filterFieldsByNameTransformer,
|
||||
name: 'Filter by name',
|
||||
name: standardTransformers.filterFieldsByNameTransformer.name,
|
||||
description: 'Removes part of the query results using a regex pattern. The pattern can be inclusive or exclusive.',
|
||||
categories: new Set([TransformerCategory.Filter]),
|
||||
help: getTransformationContent(DataTransformerID.filterFieldsByName).helperDocs,
|
||||
};
|
||||
|
@ -11,6 +11,8 @@ import {
|
||||
import { FilterFramesByRefIdTransformerOptions } from '@grafana/data/src/transformations/transformers/filterByRefId';
|
||||
import { HorizontalGroup, FilterPill, FieldValidationMessage } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
interface FilterByRefIdTransformerEditorProps extends TransformerUIProps<FilterFramesByRefIdTransformerOptions> {}
|
||||
|
||||
interface FilterByRefIdTransformerEditorState {
|
||||
@ -143,8 +145,9 @@ export const filterFramesByRefIdTransformRegistryItem: TransformerRegistryItem<F
|
||||
id: DataTransformerID.filterByRefId,
|
||||
editor: FilterByRefIdTransformerEditor,
|
||||
transformation: standardTransformers.filterFramesByRefIdTransformer,
|
||||
name: 'Filter data by query',
|
||||
name: standardTransformers.filterFramesByRefIdTransformer.name,
|
||||
description:
|
||||
'Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel.',
|
||||
categories: new Set([TransformerCategory.Filter]),
|
||||
help: getTransformationContent(DataTransformerID.filterByRefId).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
import { FormatTimeTransformerOptions } from '@grafana/data/src/transformations/transformers/formatTime';
|
||||
import { Select, InlineFieldRow, InlineField, Input } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { getTimezoneOptions } from '../utils';
|
||||
|
||||
export function FormatTimeTransfomerEditor({
|
||||
@ -109,4 +110,5 @@ export const formatTimeTransformerRegistryItem: TransformerRegistryItem<FormatTi
|
||||
name: standardTransformers.formatTimeTransformer.name,
|
||||
state: PluginState.alpha,
|
||||
description: standardTransformers.formatTimeTransformer.description,
|
||||
help: getTransformationContent(DataTransformerID.formatTime).helperDocs,
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
} from '@grafana/data/src/transformations/transformers/groupBy';
|
||||
import { useTheme2, Select, StatsPicker, InlineField, Stack } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||
|
||||
interface FieldProps {
|
||||
@ -133,4 +134,5 @@ export const groupByTransformRegistryItem: TransformerRegistryItem<GroupByTransf
|
||||
TransformerCategory.CalculateNewFields,
|
||||
TransformerCategory.Reformat,
|
||||
]),
|
||||
help: getTransformationContent(DataTransformerID.groupBy).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, Select } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||
|
||||
export const GroupingToMatrixTransformerEditor = ({
|
||||
@ -92,7 +93,8 @@ export const groupingToMatrixTransformRegistryItem: TransformerRegistryItem<Grou
|
||||
id: DataTransformerID.groupingToMatrix,
|
||||
editor: GroupingToMatrixTransformerEditor,
|
||||
transformation: standardTransformers.groupingToMatrixTransformer,
|
||||
name: 'Grouping to matrix',
|
||||
name: standardTransformers.groupingToMatrixTransformer.name,
|
||||
description: 'Takes a three fields combination and produces a Matrix.',
|
||||
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.groupingToMatrix).helperDocs,
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ import { getTemplateSrv, config as cfg } from '@grafana/runtime';
|
||||
import { InlineField, InlineFieldRow, InlineSwitch } from '@grafana/ui';
|
||||
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { SuggestionsInput } from '../suggestionsInput/SuggestionsInput';
|
||||
import { numberOrVariableValidator } from '../utils';
|
||||
|
||||
@ -189,4 +190,5 @@ export const histogramTransformRegistryItem: TransformerRegistryItem<HistogramTr
|
||||
name: standardTransformers.histogramTransformer.name,
|
||||
description: standardTransformers.histogramTransformer.description,
|
||||
categories: new Set([TransformerCategory.CreateNewVisualization]),
|
||||
help: getTransformationContent(DataTransformerID.histogram).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import { JoinByFieldOptions, JoinMode } from '@grafana/data/src/transformations/
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
import { Select, InlineFieldRow, InlineField } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||
|
||||
const modes = [
|
||||
@ -88,4 +89,5 @@ export const joinByFieldTransformerRegistryItem: TransformerRegistryItem<JoinByF
|
||||
name: standardTransformers.joinByFieldTransformer.name,
|
||||
description: standardTransformers.joinByFieldTransformer.description,
|
||||
categories: new Set([TransformerCategory.Combine]),
|
||||
help: getTransformationContent(DataTransformerID.joinByField).helperDocs,
|
||||
};
|
||||
|
@ -14,6 +14,8 @@ import {
|
||||
} from '@grafana/data/src/transformations/transformers/labelsToFields';
|
||||
import { InlineField, InlineFieldRow, RadioButtonGroup, Select, FilterPill, Stack } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
const modes: Array<SelectableValue<LabelsToFieldsMode>> = [
|
||||
{ value: LabelsToFieldsMode.Columns, label: 'Columns' },
|
||||
{ value: LabelsToFieldsMode.Rows, label: 'Rows' },
|
||||
@ -124,8 +126,9 @@ export const labelsToFieldsTransformerRegistryItem: TransformerRegistryItem<Labe
|
||||
id: DataTransformerID.labelsToFields,
|
||||
editor: LabelsAsFieldsTransformerEditor,
|
||||
transformation: standardTransformers.labelsToFieldsTransformer,
|
||||
name: 'Labels to fields',
|
||||
name: standardTransformers.labelsToFieldsTransformer.name,
|
||||
description: `Groups series by time and return labels or tags as fields.
|
||||
Useful for showing time series with labels in a table where each label key becomes a separate column.`,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.labelsToFields).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import { LimitTransformerOptions } from '@grafana/data/src/transformations/trans
|
||||
import { getTemplateSrv, config as cfg } from '@grafana/runtime';
|
||||
import { InlineField, InlineFieldRow, Input } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { SuggestionsInput } from '../suggestionsInput/SuggestionsInput';
|
||||
import { numberOrVariableValidator } from '../utils';
|
||||
|
||||
@ -81,7 +82,8 @@ export const limitTransformRegistryItem: TransformerRegistryItem<LimitTransforme
|
||||
id: DataTransformerID.limit,
|
||||
editor: LimitTransformerEditor,
|
||||
transformation: standardTransformers.limitTransformer,
|
||||
name: 'Limit',
|
||||
name: standardTransformers.limitTransformer.name,
|
||||
description: `Limit the number of items displayed.`,
|
||||
categories: new Set([TransformerCategory.Filter]),
|
||||
help: getTransformationContent(DataTransformerID.limit).helperDocs,
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ import {
|
||||
import { MergeTransformerOptions } from '@grafana/data/src/transformations/transformers/merge';
|
||||
import { FieldValidationMessage } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
export const MergeTransformerEditor = ({ input, options, onChange }: TransformerUIProps<MergeTransformerOptions>) => {
|
||||
if (input.length <= 1) {
|
||||
// Show warning that merge is useless only apply on a single frame
|
||||
@ -22,8 +24,9 @@ export const mergeTransformerRegistryItem: TransformerRegistryItem<MergeTransfor
|
||||
id: DataTransformerID.merge,
|
||||
editor: MergeTransformerEditor,
|
||||
transformation: standardTransformers.mergeTransformer,
|
||||
name: 'Merge',
|
||||
name: standardTransformers.mergeTransformer.name,
|
||||
description: `Merge many series/tables and return a single table where mergeable values will be combined into the same row.
|
||||
Useful for showing multiple series, tables or a combination of both visualized in a table.`,
|
||||
categories: new Set([TransformerCategory.Combine]),
|
||||
help: getTransformationContent(DataTransformerID.merge).helperDocs,
|
||||
};
|
||||
|
@ -14,6 +14,7 @@ import { createOrderFieldsComparer } from '@grafana/data/src/transformations/tra
|
||||
import { OrganizeFieldsTransformerOptions } from '@grafana/data/src/transformations/transformers/organize';
|
||||
import { Input, IconButton, Icon, FieldValidationMessage, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||
|
||||
interface OrganizeFieldsTransformerEditorProps extends TransformerUIProps<OrganizeFieldsTransformerOptions> {}
|
||||
@ -206,8 +207,9 @@ export const organizeFieldsTransformRegistryItem: TransformerRegistryItem<Organi
|
||||
id: DataTransformerID.organize,
|
||||
editor: OrganizeFieldsTransformerEditor,
|
||||
transformation: standardTransformers.organizeFieldsTransformer,
|
||||
name: 'Organize fields',
|
||||
name: standardTransformers.organizeFieldsTransformer.name,
|
||||
description:
|
||||
"Allows the user to re-order, hide, or rename fields / columns. Useful when data source doesn't allow overrides for visualizing data.",
|
||||
categories: new Set([TransformerCategory.ReorderAndRename]),
|
||||
help: getTransformationContent(DataTransformerID.organize).helperDocs,
|
||||
};
|
||||
|
@ -13,6 +13,8 @@ import { ReduceTransformerMode, ReduceTransformerOptions } from '@grafana/data/s
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { InlineField, Select, StatsPicker, InlineSwitch } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
// TODO: Minimal implementation, needs some <3
|
||||
export const ReduceTransformerEditor = ({ options, onChange }: TransformerUIProps<ReduceTransformerOptions>) => {
|
||||
const modes: Array<SelectableValue<ReduceTransformerMode>> = [
|
||||
@ -102,4 +104,5 @@ export const reduceTransformRegistryItem: TransformerRegistryItem<ReduceTransfor
|
||||
name: standardTransformers.reduceTransformer.name,
|
||||
description: standardTransformers.reduceTransformer.description,
|
||||
categories: new Set([TransformerCategory.CalculateNewFields]),
|
||||
help: getTransformationContent(DataTransformerID.reduce).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,8 @@ import {
|
||||
import { RenameByRegexTransformerOptions } from '@grafana/data/src/transformations/transformers/renameByRegex';
|
||||
import { Field, Input } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
interface RenameByRegexTransformerEditorProps extends TransformerUIProps<RenameByRegexTransformerOptions> {}
|
||||
|
||||
interface RenameByRegexTransformerEditorState {
|
||||
@ -128,7 +130,8 @@ export const renameByRegexTransformRegistryItem: TransformerRegistryItem<RenameB
|
||||
id: DataTransformerID.renameByRegex,
|
||||
editor: RenameByRegexTransformerEditor,
|
||||
transformation: standardTransformers.renameByRegexTransformer,
|
||||
name: 'Rename by regex',
|
||||
name: standardTransformers.renameByRegexTransformer.name,
|
||||
description: 'Renames part of the query result by using regular expression with placeholders.',
|
||||
categories: new Set([TransformerCategory.ReorderAndRename]),
|
||||
help: getTransformationContent(DataTransformerID.renameByRegex).helperDocs,
|
||||
};
|
||||
|
@ -7,6 +7,8 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { SeriesToRowsTransformerOptions } from '@grafana/data/src/transformations/transformers/seriesToRows';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
export const SeriesToRowsTransformerEditor = ({
|
||||
input,
|
||||
options,
|
||||
@ -19,8 +21,9 @@ export const seriesToRowsTransformerRegistryItem: TransformerRegistryItem<Series
|
||||
id: DataTransformerID.seriesToRows,
|
||||
editor: SeriesToRowsTransformerEditor,
|
||||
transformation: standardTransformers.seriesToRowsTransformer,
|
||||
name: 'Series to rows',
|
||||
name: standardTransformers.seriesToRowsTransformer.name,
|
||||
description: `Merge many series and return a single series with time, metric and value as columns.
|
||||
Useful for showing multiple time series visualized in a table.`,
|
||||
categories: new Set([TransformerCategory.Combine, TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.seriesToRows).helperDocs,
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ import { SortByField, SortByTransformerOptions } from '@grafana/data/src/transfo
|
||||
import { getTemplateSrv, config as cfg } from '@grafana/runtime';
|
||||
import { InlineField, InlineSwitch, InlineFieldRow, Select } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { useAllFieldNamesFromDataFrames } from '../utils';
|
||||
|
||||
export const SortByTransformerEditor = ({ input, options, onChange }: TransformerUIProps<SortByTransformerOptions>) => {
|
||||
@ -65,4 +66,5 @@ export const sortByTransformRegistryItem: TransformerRegistryItem<SortByTransfor
|
||||
name: standardTransformers.sortByTransformer.name,
|
||||
description: standardTransformers.sortByTransformer.description,
|
||||
categories: new Set([TransformerCategory.ReorderAndRename]),
|
||||
help: getTransformationContent(DataTransformerID.sortBy).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,8 @@ import {
|
||||
import { InlineField, InlineFieldRow, Select, InlineSwitch } from '@grafana/ui';
|
||||
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { JSONPathEditor } from './components/JSONPathEditor';
|
||||
import { extractFieldsTransformer } from './extractFields';
|
||||
import { fieldExtractors } from './fieldExtractors';
|
||||
@ -117,7 +119,8 @@ export const extractFieldsTransformRegistryItem: TransformerRegistryItem<Extract
|
||||
id: DataTransformerID.extractFields,
|
||||
editor: extractFieldsTransformerEditor,
|
||||
transformation: extractFieldsTransformer,
|
||||
name: 'Extract fields',
|
||||
name: extractFieldsTransformer.name,
|
||||
description: `Parse fields from content (JSON, labels, etc).`,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.extractFields).helperDocs,
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { Alert, HorizontalGroup, InlineField, InlineFieldRow, Select, ValuePicker } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { getDistinctLabels } from '../utils';
|
||||
|
||||
import { joinByLabelsTransformer, JoinByLabelsTransformOptions } from './joinByLabels';
|
||||
@ -163,9 +164,5 @@ export const joinByLabelsTransformRegistryItem: TransformerRegistryItem<JoinByLa
|
||||
description: joinByLabelsTransformer.description,
|
||||
state: PluginState.beta,
|
||||
categories: new Set([TransformerCategory.Combine]),
|
||||
// help: `
|
||||
// ### Use cases
|
||||
|
||||
// This transforms labeled results into a table
|
||||
// `,
|
||||
help: getTransformationContent(joinByLabelsTransformer.id).helperDocs,
|
||||
};
|
||||
|
@ -14,6 +14,8 @@ import { InlineField, InlineFieldRow } from '@grafana/ui';
|
||||
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
|
||||
import { GazetteerPathEditor, GazetteerPathEditorConfigSettings } from 'app/features/geo/editor/GazetteerPathEditor';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { FieldLookupOptions, fieldLookupTransformer } from './fieldLookup';
|
||||
|
||||
const fieldNamePickerSettings: StandardEditorsRegistryItem<string, FieldNamePickerConfigSettings> = {
|
||||
@ -82,8 +84,9 @@ export const fieldLookupTransformRegistryItem: TransformerRegistryItem<FieldLook
|
||||
id: DataTransformerID.fieldLookup,
|
||||
editor: FieldLookupTransformerEditor,
|
||||
transformation: fieldLookupTransformer,
|
||||
name: 'Field lookup',
|
||||
name: fieldLookupTransformer.name,
|
||||
description: `Use a field value to lookup additional fields from an external source. This currently supports spatial data, but will eventually support more formats.`,
|
||||
state: PluginState.alpha,
|
||||
categories: new Set([TransformerCategory.PerformSpatialOperations]),
|
||||
help: getTransformationContent(DataTransformerID.fieldLookup).helperDocs,
|
||||
};
|
||||
|
@ -19,6 +19,8 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/src/components/MatchersUI/utils';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { partitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues';
|
||||
|
||||
export function PartitionByValuesEditor({
|
||||
@ -145,4 +147,5 @@ export const partitionByValuesTransformRegistryItem: TransformerRegistryItem<Par
|
||||
description: partitionByValuesTransformer.description,
|
||||
state: PluginState.alpha,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(DataTransformerID.partitionByValues).helperDocs,
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, Select, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { prepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries';
|
||||
|
||||
const wideInfo = {
|
||||
@ -118,12 +120,6 @@ export const prepareTimeseriesTransformerRegistryItem: TransformerRegistryItem<P
|
||||
transformation: prepareTimeSeriesTransformer,
|
||||
name: prepareTimeSeriesTransformer.name,
|
||||
description: prepareTimeSeriesTransformer.description,
|
||||
help: `
|
||||
### Use cases
|
||||
|
||||
This takes query results and transforms them into a predictable timeseries format.
|
||||
This transformer may be especially useful when using old panels that only expect the
|
||||
many-frame timeseries format.
|
||||
`,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: getTransformationContent(prepareTimeSeriesTransformer.id).helperDocs,
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
|
||||
import { PluginState, TransformerRegistryItem, TransformerUIProps, TransformerCategory } from '@grafana/data';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
import { FieldToConfigMappingEditor } from '../fieldToConfigMapping/FieldToConfigMappingEditor';
|
||||
|
||||
import { rowsToFieldsTransformer, RowToFieldsTransformOptions } from './rowsToFields';
|
||||
@ -33,39 +34,5 @@ export const rowsToFieldsTransformRegistryItem: TransformerRegistryItem<RowToFie
|
||||
description: rowsToFieldsTransformer.description,
|
||||
state: PluginState.beta,
|
||||
categories: new Set([TransformerCategory.Reformat]),
|
||||
help: `
|
||||
### Use cases
|
||||
|
||||
This transforms rows into separate fields. This can be useful as fields can be styled and configured
|
||||
individually, something rows cannot. It can also use additional fields as sources for dynamic field
|
||||
configuration or map them to field labels. The additional labels can then be used to define better
|
||||
display names for the resulting fields.
|
||||
|
||||
Useful when visualization data in:
|
||||
- Gauge
|
||||
- Stat
|
||||
- Pie chart
|
||||
|
||||
## Example
|
||||
|
||||
Input:
|
||||
|
||||
| Name | Value | Max |
|
||||
| ------- | ----- | --- |
|
||||
| ServerA | 10 | 100 |
|
||||
| ServerB | 20 | 200 |
|
||||
| ServerC | 30 | 300 |
|
||||
|
||||
Output:
|
||||
|
||||
| ServerA (config: max=100) | ServerB (config: max=200) | ServerC (config: max=300) |
|
||||
| ------------------------- | ------------------------- | ------------------------- |
|
||||
| 10 | 20 | 30 |
|
||||
|
||||
As you can see each row in the source data becomes a separate field. Each field now also has a max
|
||||
config option set. Options like **Min**, **Max**, **Unit** and **Thresholds** are all part of field
|
||||
configuration and if set like this will be used by the visualization instead of any options manually
|
||||
configured in the panel editor options pane.
|
||||
|
||||
`,
|
||||
help: getTransformationContent(rowsToFieldsTransformer.id).helperDocs,
|
||||
};
|
||||
|
@ -15,6 +15,8 @@ import { FrameGeometrySourceMode } from '@grafana/schema';
|
||||
import { useTheme2 } from '@grafana/ui';
|
||||
import { addLocationFields } from 'app/features/geo/editor/locationEditor';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import { SpatialCalculation, SpatialOperation, SpatialAction, SpatialTransformOptions } from './models.gen';
|
||||
import { getDefaultOptions, getTransformerOptionPane } from './optionsHelper';
|
||||
import { isLineBuilderOption, spatialTransformer } from './spatialTransformer';
|
||||
@ -165,4 +167,5 @@ export const spatialTransformRegistryItem: TransformerRegistryItem<SpatialTransf
|
||||
description: spatialTransformer.description,
|
||||
state: PluginState.alpha,
|
||||
categories: new Set([TransformerCategory.PerformSpatialOperations]),
|
||||
help: getTransformationContent(DataTransformerID.spatial).helperDocs,
|
||||
};
|
||||
|
@ -12,6 +12,8 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { InlineFieldRow, InlineField, StatsPicker, Select, InlineLabel } from '@grafana/ui';
|
||||
|
||||
import { getTransformationContent } from '../docs/getTransformationContent';
|
||||
|
||||
import {
|
||||
timeSeriesTableTransformer,
|
||||
TimeSeriesTableTransformerOptions,
|
||||
@ -117,5 +119,5 @@ export const timeSeriesTableTransformRegistryItem: TransformerRegistryItem<TimeS
|
||||
name: timeSeriesTableTransformer.name,
|
||||
description: timeSeriesTableTransformer.description,
|
||||
state: PluginState.beta,
|
||||
help: ``,
|
||||
help: getTransformationContent(timeSeriesTableTransformer.id).helperDocs,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user