mirror of
https://github.com/grafana/grafana.git
synced 2024-12-26 17:01:09 -06:00
Transformations: Fixed transformation crash issue (#25152)
* Transformations: Fixed transformation crash issue * Updated
This commit is contained in:
parent
6a4f45625c
commit
3833aa416d
26
e2e/suite1/specs/panelEdit_transforms.spec.ts
Normal file
26
e2e/suite1/specs/panelEdit_transforms.spec.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
const PANEL_UNDER_TEST = 'Random walk series';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Panel edit tests - transformations',
|
||||
itName: 'Tests transformations editor',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e.flows.openDashboard('5SdHCadmz');
|
||||
|
||||
e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST);
|
||||
|
||||
e2e.components.Tab.title('Transform')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
e2e.components.TransformTab.newTransform('Reduce')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
e2e.components.Transforms.Reduce.calculationsLabel().should('be.visible');
|
||||
},
|
||||
});
|
@ -97,6 +97,12 @@ export const Components = {
|
||||
},
|
||||
TransformTab: {
|
||||
content: 'Transform editor tab content',
|
||||
newTransform: (title: string) => `New transform ${title}`,
|
||||
},
|
||||
Transforms: {
|
||||
Reduce: {
|
||||
calculationsLabel: 'Transform calculations label',
|
||||
},
|
||||
},
|
||||
QueryEditorToolbarItem: {
|
||||
button: (title: string) => `QueryEditor toolbar item button ${title}`,
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
|
||||
import { ReduceTransformerOptions } from '@grafana/data/src/transformations/transformers/reduce';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
// TODO: Minimal implementation, needs some <3
|
||||
export const ReduceTransformerEditor: React.FC<TransformerUIProps<ReduceTransformerOptions>> = ({
|
||||
@ -18,7 +19,9 @@ export const ReduceTransformerEditor: React.FC<TransformerUIProps<ReduceTransfor
|
||||
return (
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form gf-form--grow">
|
||||
<div className="gf-form-label width-8">Calculations</div>
|
||||
<div className="gf-form-label width-8" aria-label={selectors.components.Transforms.Reduce.calculationsLabel}>
|
||||
Calculations
|
||||
</div>
|
||||
<StatsPicker
|
||||
className="flex-grow-1"
|
||||
placeholder="Choose Stat"
|
||||
|
@ -2,7 +2,6 @@ import React, { useCallback } from 'react';
|
||||
import { config } from 'app/core/config';
|
||||
import { css } from 'emotion';
|
||||
import { IconName, stylesFactory, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||
import { DataTransformerConfig } from '@grafana/data';
|
||||
import { PanelEditorTab, PanelEditorTabId } from './types';
|
||||
import { DashboardModel } from '../../state';
|
||||
import { QueriesTab } from '../../panel_editor/QueriesTab';
|
||||
@ -42,10 +41,6 @@ export const PanelEditorTabs: React.FC<PanelEditorTabsProps> = ({ panel, dashboa
|
||||
return null;
|
||||
}
|
||||
|
||||
const onTransformersChange = (transformers: DataTransformerConfig[]) => {
|
||||
panel.setTransformations(transformers);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<TabsBar className={styles.tabBar}>
|
||||
@ -65,13 +60,7 @@ export const PanelEditorTabs: React.FC<PanelEditorTabsProps> = ({ panel, dashboa
|
||||
<TabContent className={styles.tabContent}>
|
||||
{activeTab.id === PanelEditorTabId.Query && <QueriesTab panel={panel} dashboard={dashboard} />}
|
||||
{activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
|
||||
{activeTab.id === PanelEditorTabId.Transform && (
|
||||
<TransformationsEditor
|
||||
transformations={panel.transformations || []}
|
||||
onChange={onTransformersChange}
|
||||
panel={panel}
|
||||
/>
|
||||
)}
|
||||
{activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
|
||||
</TabContent>
|
||||
</div>
|
||||
);
|
||||
|
@ -28,17 +28,25 @@ import { PanelModel } from '../../state';
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
onChange: (transformations: DataTransformerConfig[]) => void;
|
||||
transformations: DataTransformerConfig[];
|
||||
}
|
||||
|
||||
interface State {
|
||||
data?: DataFrame[];
|
||||
data: DataFrame[];
|
||||
transformations: DataTransformerConfig[];
|
||||
}
|
||||
|
||||
export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
subscription?: Unsubscribable;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
transformations: props.panel.transformations || [],
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.subscription = this.props.panel
|
||||
.getQueryRunner()
|
||||
@ -54,9 +62,15 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
onChange(transformations: DataTransformerConfig[]) {
|
||||
this.props.panel.setTransformations(transformations);
|
||||
this.setState({ transformations });
|
||||
}
|
||||
|
||||
onTransformationAdd = (selectable: SelectableValue<string>) => {
|
||||
const { transformations, onChange } = this.props;
|
||||
onChange([
|
||||
const { transformations } = this.state;
|
||||
|
||||
this.onChange([
|
||||
...transformations,
|
||||
{
|
||||
id: selectable.value as string,
|
||||
@ -66,17 +80,17 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
onTransformationChange = (idx: number, config: DataTransformerConfig) => {
|
||||
const { transformations, onChange } = this.props;
|
||||
const { transformations } = this.state;
|
||||
const next = Array.from(transformations);
|
||||
next[idx] = config;
|
||||
onChange(next);
|
||||
this.onChange(next);
|
||||
};
|
||||
|
||||
onTransformationRemove = (idx: number) => {
|
||||
const { transformations, onChange } = this.props;
|
||||
const { transformations } = this.state;
|
||||
const next = Array.from(transformations);
|
||||
next.splice(idx, 1);
|
||||
onChange(next);
|
||||
this.onChange(next);
|
||||
};
|
||||
|
||||
renderTransformationSelector = () => {
|
||||
@ -108,10 +122,7 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
renderTransformationEditors = () => {
|
||||
const { transformations } = this.props;
|
||||
const { data } = this.state;
|
||||
|
||||
const preTransformData = data ?? [];
|
||||
const { data, transformations } = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -123,7 +134,7 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
return null;
|
||||
}
|
||||
|
||||
const input = transformDataFrame(transformations.slice(0, i), preTransformData);
|
||||
const input = transformDataFrame(transformations.slice(0, i), data);
|
||||
const output = transformDataFrame(transformations.slice(i), input);
|
||||
|
||||
if (transformationUI) {
|
||||
@ -182,6 +193,7 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
title={t.name}
|
||||
description={t.description}
|
||||
actions={<Button>Select</Button>}
|
||||
ariaLabel={selectors.components.TransformTab.newTransform(t.name)}
|
||||
onClick={() => {
|
||||
this.onTransformationAdd({ value: t.id });
|
||||
}}
|
||||
@ -194,14 +206,17 @@ export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const hasTransformationsConfigured = this.props.transformations.length > 0;
|
||||
const { transformations } = this.state;
|
||||
|
||||
const hasTransforms = transformations.length > 0;
|
||||
|
||||
return (
|
||||
<CustomScrollbar autoHeightMin="100%">
|
||||
<Container padding="md">
|
||||
<div aria-label={selectors.components.TransformTab.content}>
|
||||
{!hasTransformationsConfigured && this.renderNoAddedTransformsState()}
|
||||
{hasTransformationsConfigured && this.renderTransformationEditors()}
|
||||
{hasTransformationsConfigured && this.renderTransformationSelector()}
|
||||
{!hasTransforms && this.renderNoAddedTransformsState()}
|
||||
{hasTransforms && this.renderTransformationEditors()}
|
||||
{hasTransforms && this.renderTransformationSelector()}
|
||||
</div>
|
||||
</Container>
|
||||
</CustomScrollbar>
|
||||
|
Loading…
Reference in New Issue
Block a user