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:
Jev Forsberg 2023-11-07 09:29:45 -07:00 committed by GitHub
parent 30f2ab07f5
commit a99485ba33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 350 additions and 206 deletions

View File

@ -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

View File

@ -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');

View File

@ -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;

View File

@ -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();
});
});

View File

@ -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>
);
};

View File

@ -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.
`;
}

View File

@ -22,6 +22,7 @@ export const TransformationOperationRows = ({
<>
{configs.map((t, i) => {
const uiConfig = standardTransformersRegistry.getIfExists(t.transformation.id);
if (!uiConfig) {
return null;
}

View File

@ -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 => {

View File

@ -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,
};

View File

@ -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) => ({

View File

@ -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.
`![${imageName} helper image](${source})`;
`![${imageName} helper image](https://grafana.com${source})`;
}

View File

@ -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;
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};