mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PanelEditor: Overrides name matcher still show all original field names even after Field default display name is specified (#24933)
* FieldConfigOverrides: Should not apply defaults in override UI options * Missed change
This commit is contained in:
@@ -35,7 +35,7 @@ export const OptionsPaneContent: React.FC<Props> = ({
|
||||
const styles = getStyles(theme);
|
||||
const [activeTab, setActiveTab] = useState('options');
|
||||
const [isSearching, setSearchMode] = useState(false);
|
||||
const [currentData, hasSeries] = usePanelLatestData(panel);
|
||||
const [currentData, hasSeries] = usePanelLatestData(panel, { withTransforms: true, withFieldConfig: false });
|
||||
|
||||
const renderFieldOptions = useCallback(
|
||||
(plugin: PanelPlugin) => {
|
||||
|
||||
@@ -51,11 +51,13 @@ export const OverrideEditor: React.FC<OverrideEditorProps> = ({
|
||||
const theme = useTheme();
|
||||
const matcherUi = fieldMatchersUI.get(override.matcher.id);
|
||||
const styles = getStyles(theme);
|
||||
|
||||
const matcherLabel = (
|
||||
<Label category={['Matcher']} description={matcherUi.description}>
|
||||
{matcherUi.name}
|
||||
</Label>
|
||||
);
|
||||
|
||||
const onMatcherConfigChange = useCallback(
|
||||
(matcherConfig: any) => {
|
||||
override.matcher.options = matcherConfig;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { FieldConfigSource, GrafanaTheme, PanelData, PanelPlugin } from '@grafana/data';
|
||||
import { FieldConfigSource, GrafanaTheme, PanelPlugin } from '@grafana/data';
|
||||
import { Button, HorizontalGroup, Icon, RadioButtonGroup, stylesFactory } from '@grafana/ui';
|
||||
import { css, cx } from 'emotion';
|
||||
import config from 'app/core/config';
|
||||
@@ -42,7 +42,6 @@ interface ConnectedProps {
|
||||
location: LocationState;
|
||||
plugin?: PanelPlugin;
|
||||
panel: PanelModel;
|
||||
data: PanelData;
|
||||
initDone: boolean;
|
||||
tabs: PanelEditorTab[];
|
||||
uiState: PanelEditorUIState;
|
||||
@@ -183,7 +182,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
);
|
||||
};
|
||||
renderHorizontalSplit(styles: EditorStyles) {
|
||||
const { dashboard, panel, tabs, data, uiState } = this.props;
|
||||
const { dashboard, panel, tabs, uiState } = this.props;
|
||||
return tabs.length > 0 ? (
|
||||
<SplitPane
|
||||
split="horizontal"
|
||||
@@ -198,7 +197,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
>
|
||||
{this.renderPanel(styles)}
|
||||
<div className={styles.tabsWrapper} aria-label={selectors.components.PanelEditor.DataPane.content}>
|
||||
<PanelEditorTabs panel={panel} dashboard={dashboard} tabs={tabs} onChangeTab={this.onChangeTab} data={data} />
|
||||
<PanelEditorTabs panel={panel} dashboard={dashboard} tabs={tabs} onChangeTab={this.onChangeTab} />
|
||||
</div>
|
||||
</SplitPane>
|
||||
) : (
|
||||
@@ -350,7 +349,6 @@ const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (
|
||||
location: state.location,
|
||||
plugin: plugin,
|
||||
panel,
|
||||
data: state.panelEditor.getData(),
|
||||
initDone: state.panelEditor.initDone,
|
||||
tabs: getPanelEditorTabs(state.location, plugin),
|
||||
uiState: state.panelEditor.ui,
|
||||
|
||||
@@ -2,7 +2,7 @@ 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, LoadingState, PanelData } from '@grafana/data';
|
||||
import { DataTransformerConfig } from '@grafana/data';
|
||||
import { PanelEditorTab, PanelEditorTabId } from './types';
|
||||
import { DashboardModel } from '../../state';
|
||||
import { QueriesTab } from '../../panel_editor/QueriesTab';
|
||||
@@ -15,12 +15,12 @@ interface PanelEditorTabsProps {
|
||||
dashboard: DashboardModel;
|
||||
tabs: PanelEditorTab[];
|
||||
onChangeTab: (tab: PanelEditorTab) => void;
|
||||
data: PanelData;
|
||||
}
|
||||
|
||||
export const PanelEditorTabs: React.FC<PanelEditorTabsProps> = ({ panel, dashboard, tabs, data, onChangeTab }) => {
|
||||
export const PanelEditorTabs: React.FC<PanelEditorTabsProps> = ({ panel, dashboard, tabs, onChangeTab }) => {
|
||||
const styles = getPanelEditorTabsStyles();
|
||||
const activeTab = tabs.find(item => item.active);
|
||||
|
||||
const getCounter = useCallback(
|
||||
(tab: PanelEditorTab) => {
|
||||
switch (tab.id) {
|
||||
@@ -65,11 +65,11 @@ 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 && data.state !== LoadingState.NotStarted && (
|
||||
{activeTab.id === PanelEditorTabId.Transform && (
|
||||
<TransformationsEditor
|
||||
transformations={panel.transformations || []}
|
||||
onChange={onTransformersChange}
|
||||
dataFrames={data.series}
|
||||
panel={panel}
|
||||
/>
|
||||
)}
|
||||
</TabContent>
|
||||
|
||||
@@ -40,7 +40,6 @@ describe('panelEditor actions', () => {
|
||||
...initialState(),
|
||||
getPanel: () => panel,
|
||||
getSourcePanel: () => sourcePanel,
|
||||
querySubscription: { unsubscribe: jest.fn() },
|
||||
};
|
||||
|
||||
const dispatchedActions = await thunkTester({
|
||||
@@ -74,7 +73,6 @@ describe('panelEditor actions', () => {
|
||||
...initialState(),
|
||||
getPanel: () => panel,
|
||||
getSourcePanel: () => sourcePanel,
|
||||
querySubscription: { unsubscribe: jest.fn() },
|
||||
};
|
||||
|
||||
const panelDestroy = (panel.destroy = jest.fn());
|
||||
@@ -112,7 +110,6 @@ describe('panelEditor actions', () => {
|
||||
shouldDiscardChanges: true,
|
||||
getPanel: () => panel,
|
||||
getSourcePanel: () => sourcePanel,
|
||||
querySubscription: { unsubscribe: jest.fn() },
|
||||
};
|
||||
|
||||
const dispatchedActions = await thunkTester({
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { DashboardModel, PanelModel } from '../../../state';
|
||||
import { PanelData } from '@grafana/data';
|
||||
import { ThunkResult } from 'app/types';
|
||||
import {
|
||||
closeCompleted,
|
||||
PANEL_EDITOR_UI_STATE_STORAGE_KEY,
|
||||
PanelEditorUIState,
|
||||
setEditorPanelData,
|
||||
setPanelEditorUIState,
|
||||
updateEditorInitState,
|
||||
} from './reducers';
|
||||
@@ -16,16 +14,10 @@ export function initPanelEditor(sourcePanel: PanelModel, dashboard: DashboardMod
|
||||
return dispatch => {
|
||||
const panel = dashboard.initEditPanel(sourcePanel);
|
||||
|
||||
const queryRunner = panel.getQueryRunner();
|
||||
const querySubscription = queryRunner.getData({ withTransforms: false }).subscribe({
|
||||
next: (data: PanelData) => dispatch(setEditorPanelData(data)),
|
||||
});
|
||||
|
||||
dispatch(
|
||||
updateEditorInitState({
|
||||
panel,
|
||||
sourcePanel,
|
||||
querySubscription,
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -34,7 +26,7 @@ export function initPanelEditor(sourcePanel: PanelModel, dashboard: DashboardMod
|
||||
export function panelEditorCleanUp(): ThunkResult<void> {
|
||||
return (dispatch, getStore) => {
|
||||
const dashboard = getStore().dashboard.getModel();
|
||||
const { getPanel, getSourcePanel, querySubscription, shouldDiscardChanges } = getStore().panelEditor;
|
||||
const { getPanel, getSourcePanel, shouldDiscardChanges } = getStore().panelEditor;
|
||||
|
||||
if (!shouldDiscardChanges) {
|
||||
const panel = getPanel();
|
||||
@@ -66,10 +58,6 @@ export function panelEditorCleanUp(): ThunkResult<void> {
|
||||
dashboard.exitPanelEditor();
|
||||
}
|
||||
|
||||
if (querySubscription) {
|
||||
querySubscription.unsubscribe();
|
||||
}
|
||||
|
||||
dispatch(cleanUpEditPanel());
|
||||
dispatch(closeCompleted());
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { PanelModel } from '../../../state/PanelModel';
|
||||
import { DefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
|
||||
@@ -31,7 +30,6 @@ export interface PanelEditorState {
|
||||
getSourcePanel: () => PanelModel;
|
||||
getPanel: () => PanelModel;
|
||||
getData: () => PanelData;
|
||||
querySubscription?: Unsubscribable;
|
||||
initDone: boolean;
|
||||
shouldDiscardChanges: boolean;
|
||||
isOpen: boolean;
|
||||
@@ -60,7 +58,6 @@ export const initialState = (): PanelEditorState => {
|
||||
interface InitEditorPayload {
|
||||
panel: PanelModel;
|
||||
sourcePanel: PanelModel;
|
||||
querySubscription: Unsubscribable;
|
||||
}
|
||||
|
||||
const pluginsSlice = createSlice({
|
||||
@@ -70,7 +67,6 @@ const pluginsSlice = createSlice({
|
||||
updateEditorInitState: (state, action: PayloadAction<InitEditorPayload>) => {
|
||||
state.getPanel = () => action.payload.panel;
|
||||
state.getSourcePanel = () => action.payload.sourcePanel;
|
||||
state.querySubscription = action.payload.querySubscription;
|
||||
state.initDone = true;
|
||||
state.isOpen = true;
|
||||
state.shouldDiscardChanges = false;
|
||||
|
||||
@@ -2,15 +2,16 @@ import { PanelData } from '@grafana/data';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { PanelModel } from '../../state';
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
import { GetDataOptions } from '../../state/PanelQueryRunner';
|
||||
|
||||
export const usePanelLatestData = (panel: PanelModel): [PanelData | null, boolean] => {
|
||||
export const usePanelLatestData = (panel: PanelModel, options: GetDataOptions): [PanelData | null, boolean] => {
|
||||
const querySubscription = useRef<Unsubscribable>(null);
|
||||
const [latestData, setLatestData] = useState<PanelData>(null);
|
||||
|
||||
useEffect(() => {
|
||||
querySubscription.current = panel
|
||||
.getQueryRunner()
|
||||
.getData()
|
||||
.getData(options)
|
||||
.subscribe({
|
||||
next: data => setLatestData(data),
|
||||
});
|
||||
|
||||
@@ -10,26 +10,50 @@ import {
|
||||
VerticalGroup,
|
||||
} from '@grafana/ui';
|
||||
import {
|
||||
DataFrame,
|
||||
DataTransformerConfig,
|
||||
FeatureState,
|
||||
GrafanaTheme,
|
||||
SelectableValue,
|
||||
standardTransformersRegistry,
|
||||
transformDataFrame,
|
||||
DataFrame,
|
||||
PanelData,
|
||||
} from '@grafana/data';
|
||||
import { TransformationOperationRow } from './TransformationOperationRow';
|
||||
import { Card, CardProps } from '../../../../core/components/Card/Card';
|
||||
import { css } from 'emotion';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
import { PanelModel } from '../../state';
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
onChange: (transformations: DataTransformerConfig[]) => void;
|
||||
transformations: DataTransformerConfig[];
|
||||
dataFrames: DataFrame[];
|
||||
}
|
||||
|
||||
export class TransformationsEditor extends React.PureComponent<Props> {
|
||||
interface State {
|
||||
data?: DataFrame[];
|
||||
}
|
||||
|
||||
export class TransformationsEditor extends React.PureComponent<Props, State> {
|
||||
subscription?: Unsubscribable;
|
||||
|
||||
componentDidMount() {
|
||||
this.subscription = this.props.panel
|
||||
.getQueryRunner()
|
||||
.getData({ withTransforms: false, withFieldConfig: false })
|
||||
.subscribe({
|
||||
next: (panelData: PanelData) => this.setState({ data: panelData.series }),
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
onTransformationAdd = (selectable: SelectableValue<string>) => {
|
||||
const { transformations, onChange } = this.props;
|
||||
onChange([
|
||||
@@ -84,8 +108,10 @@ export class TransformationsEditor extends React.PureComponent<Props> {
|
||||
};
|
||||
|
||||
renderTransformationEditors = () => {
|
||||
const { transformations, dataFrames } = this.props;
|
||||
const preTransformData = dataFrames;
|
||||
const { transformations } = this.props;
|
||||
const { data } = this.state;
|
||||
|
||||
const preTransformData = data ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -70,7 +70,7 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { panel, dashboard, isEditing } = this.props;
|
||||
const { panel, dashboard } = this.props;
|
||||
|
||||
panel.events.on(PanelEvents.refresh, this.onRefresh);
|
||||
panel.events.on(PanelEvents.render, this.onRender);
|
||||
@@ -87,29 +87,19 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
},
|
||||
isFirstLoad: false,
|
||||
});
|
||||
} else {
|
||||
if (isEditing) {
|
||||
this.querySubscription = panel
|
||||
.getQueryRunner()
|
||||
.getData()
|
||||
.subscribe({
|
||||
next: data => this.onDataUpdate(data),
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.wantsQueryExecution) {
|
||||
this.setState({ isFirstLoad: false });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.querySubscription) {
|
||||
this.querySubscription = panel
|
||||
.getQueryRunner()
|
||||
.getData()
|
||||
.subscribe({
|
||||
next: data => this.onDataUpdate(data),
|
||||
});
|
||||
if (!this.wantsQueryExecution) {
|
||||
this.setState({ isFirstLoad: false });
|
||||
}
|
||||
|
||||
this.querySubscription = panel
|
||||
.getQueryRunner()
|
||||
.getData({ withTransforms: true, withFieldConfig: true })
|
||||
.subscribe({
|
||||
next: data => this.onDataUpdate(data),
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
||||
@@ -78,7 +78,9 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
|
||||
|
||||
// subscribe to data events
|
||||
const queryRunner = panel.getQueryRunner();
|
||||
this.querySubscription = queryRunner.getData({ withTransforms: false }).subscribe({
|
||||
|
||||
// we are not displaying any of this data so no need for transforms or field config
|
||||
this.querySubscription = queryRunner.getData({ withTransforms: false, withFieldConfig: false }).subscribe({
|
||||
next: (data: PanelData) => this.onPanelDataUpdate(data),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ export class QueriesTab extends PureComponent<Props, State> {
|
||||
const { panel } = this.props;
|
||||
const queryRunner = panel.getQueryRunner();
|
||||
|
||||
this.querySubscription = queryRunner.getData({ withTransforms: false }).subscribe({
|
||||
this.querySubscription = queryRunner.getData({ withTransforms: false, withFieldConfig: false }).subscribe({
|
||||
next: (data: PanelData) => this.onPanelDataUpdate(data),
|
||||
});
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn
|
||||
};
|
||||
|
||||
ctx.runner = new PanelQueryRunner(panelConfig || defaultPanelConfig);
|
||||
ctx.runner.getData().subscribe({
|
||||
ctx.runner.getData({ withTransforms: true, withFieldConfig: true }).subscribe({
|
||||
next: (data: PanelData) => {
|
||||
ctx.res = data;
|
||||
ctx.events?.push(data);
|
||||
@@ -201,7 +201,7 @@ describe('PanelQueryRunner', () => {
|
||||
it('should apply when field override options are set', async () => {
|
||||
const spy = jest.spyOn(grafanaData, 'applyFieldOverrides');
|
||||
|
||||
ctx.runner.getData().subscribe({
|
||||
ctx.runner.getData({ withTransforms: true, withFieldConfig: true }).subscribe({
|
||||
next: (data: PanelData) => {
|
||||
return data;
|
||||
},
|
||||
@@ -232,7 +232,7 @@ describe('PanelQueryRunner', () => {
|
||||
const spy = jest.spyOn(grafanaData, 'transformDataFrame');
|
||||
spy.mockClear();
|
||||
|
||||
ctx.runner.getData().subscribe({
|
||||
ctx.runner.getData({ withTransforms: true, withFieldConfig: true }).subscribe({
|
||||
next: (data: PanelData) => {
|
||||
return data;
|
||||
},
|
||||
@@ -254,7 +254,7 @@ describe('PanelQueryRunner', () => {
|
||||
it('should not apply transformations when transform option is false', async () => {
|
||||
const spy = jest.spyOn(grafanaData, 'transformDataFrame');
|
||||
spy.mockClear();
|
||||
ctx.runner.getData({ withTransforms: false }).subscribe({
|
||||
ctx.runner.getData({ withTransforms: false, withFieldConfig: true }).subscribe({
|
||||
next: (data: PanelData) => {
|
||||
return data;
|
||||
},
|
||||
@@ -266,7 +266,7 @@ describe('PanelQueryRunner', () => {
|
||||
it('should not apply field config when applyFieldConfig option is false', async () => {
|
||||
const spy = jest.spyOn(grafanaData, 'applyFieldOverrides');
|
||||
spy.mockClear();
|
||||
ctx.runner.getData({ withFieldConfig: false }).subscribe({
|
||||
ctx.runner.getData({ withFieldConfig: false, withTransforms: true }).subscribe({
|
||||
next: (data: PanelData) => {
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -52,13 +52,9 @@ function getNextRequestId() {
|
||||
}
|
||||
|
||||
export interface GetDataOptions {
|
||||
withTransforms?: boolean;
|
||||
withFieldConfig?: boolean;
|
||||
withTransforms: boolean;
|
||||
withFieldConfig: boolean;
|
||||
}
|
||||
const DEFAULT_GET_DATA_OPTIONS: GetDataOptions = {
|
||||
withTransforms: true,
|
||||
withFieldConfig: true,
|
||||
};
|
||||
|
||||
export class PanelQueryRunner {
|
||||
private subject?: ReplaySubject<PanelData>;
|
||||
@@ -75,7 +71,7 @@ export class PanelQueryRunner {
|
||||
/**
|
||||
* Returns an observable that subscribes to the shared multi-cast subject (that reply last result).
|
||||
*/
|
||||
getData(options: GetDataOptions = DEFAULT_GET_DATA_OPTIONS): Observable<PanelData> {
|
||||
getData(options: GetDataOptions): Observable<PanelData> {
|
||||
const { withFieldConfig, withTransforms } = options;
|
||||
|
||||
return this.subject.pipe(
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { Unsubscribable } from 'rxjs';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { PanelQueryRunner } from '../dashboard/state/PanelQueryRunner';
|
||||
|
||||
class MetricsPanelCtrl extends PanelCtrl {
|
||||
scope: any;
|
||||
@@ -51,8 +52,10 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
}
|
||||
|
||||
private onMetricsPanelMounted() {
|
||||
const queryRunner = this.panel.getQueryRunner();
|
||||
this.querySubscription = queryRunner.getData().subscribe(this.panelDataObserver);
|
||||
const queryRunner = this.panel.getQueryRunner() as PanelQueryRunner;
|
||||
this.querySubscription = queryRunner
|
||||
.getData({ withTransforms: true, withFieldConfig: true })
|
||||
.subscribe(this.panelDataObserver);
|
||||
}
|
||||
|
||||
private onPanelTearDown() {
|
||||
|
||||
Reference in New Issue
Block a user