From 923faf78f188d66a7eae25148e66b07e137a62ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 25 May 2020 14:05:43 +0200 Subject: [PATCH] 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 --- .../PanelEditor/OptionsPaneContent.tsx | 2 +- .../components/PanelEditor/OverrideEditor.tsx | 2 ++ .../components/PanelEditor/PanelEditor.tsx | 8 ++--- .../PanelEditor/PanelEditorTabs.tsx | 10 +++--- .../PanelEditor/state/actions.test.ts | 3 -- .../components/PanelEditor/state/actions.ts | 14 +------- .../components/PanelEditor/state/reducers.ts | 4 --- .../PanelEditor/usePanelLatestData.ts | 5 +-- .../TransformationsEditor.tsx | 36 ++++++++++++++++--- .../dashboard/dashgrid/PanelChrome.tsx | 32 ++++++----------- .../dashboard/dashgrid/PanelChromeAngular.tsx | 4 ++- .../dashboard/panel_editor/QueriesTab.tsx | 2 +- .../dashboard/state/PanelQueryRunner.test.ts | 10 +++--- .../dashboard/state/PanelQueryRunner.ts | 10 ++---- .../app/features/panel/metrics_panel_ctrl.ts | 7 ++-- 15 files changed, 74 insertions(+), 75 deletions(-) diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx index 25ebbcc7e5a..0e4ac7ac0f7 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneContent.tsx @@ -35,7 +35,7 @@ export const OptionsPaneContent: React.FC = ({ 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) => { diff --git a/public/app/features/dashboard/components/PanelEditor/OverrideEditor.tsx b/public/app/features/dashboard/components/PanelEditor/OverrideEditor.tsx index a2a8a5c37db..f5123d2d71b 100644 --- a/public/app/features/dashboard/components/PanelEditor/OverrideEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OverrideEditor.tsx @@ -51,11 +51,13 @@ export const OverrideEditor: React.FC = ({ const theme = useTheme(); const matcherUi = fieldMatchersUI.get(override.matcher.id); const styles = getStyles(theme); + const matcherLabel = ( ); + const onMatcherConfigChange = useCallback( (matcherConfig: any) => { override.matcher.options = matcherConfig; diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index cbd190f001d..23a62c164a4 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -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 { ); }; renderHorizontalSplit(styles: EditorStyles) { - const { dashboard, panel, tabs, data, uiState } = this.props; + const { dashboard, panel, tabs, uiState } = this.props; return tabs.length > 0 ? ( { > {this.renderPanel(styles)}
- +
) : ( @@ -350,7 +349,6 @@ const mapStateToProps: MapStateToProps = ( location: state.location, plugin: plugin, panel, - data: state.panelEditor.getData(), initDone: state.panelEditor.initDone, tabs: getPanelEditorTabs(state.location, plugin), uiState: state.panelEditor.ui, diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx index 3205874ece0..73e6568f313 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx @@ -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 = ({ panel, dashboard, tabs, data, onChangeTab }) => { +export const PanelEditorTabs: React.FC = ({ 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 = ({ panel, dashboa {activeTab.id === PanelEditorTabId.Query && } {activeTab.id === PanelEditorTabId.Alert && } - {activeTab.id === PanelEditorTabId.Transform && data.state !== LoadingState.NotStarted && ( + {activeTab.id === PanelEditorTabId.Transform && ( )} diff --git a/public/app/features/dashboard/components/PanelEditor/state/actions.test.ts b/public/app/features/dashboard/components/PanelEditor/state/actions.test.ts index d124fbb9baf..5b4b2fd56ed 100644 --- a/public/app/features/dashboard/components/PanelEditor/state/actions.test.ts +++ b/public/app/features/dashboard/components/PanelEditor/state/actions.test.ts @@ -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({ diff --git a/public/app/features/dashboard/components/PanelEditor/state/actions.ts b/public/app/features/dashboard/components/PanelEditor/state/actions.ts index 1c5c04aab7f..52b26aeda17 100644 --- a/public/app/features/dashboard/components/PanelEditor/state/actions.ts +++ b/public/app/features/dashboard/components/PanelEditor/state/actions.ts @@ -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 { 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 { dashboard.exitPanelEditor(); } - if (querySubscription) { - querySubscription.unsubscribe(); - } - dispatch(cleanUpEditPanel()); dispatch(closeCompleted()); }; diff --git a/public/app/features/dashboard/components/PanelEditor/state/reducers.ts b/public/app/features/dashboard/components/PanelEditor/state/reducers.ts index 482ef0a9d29..9503099a219 100644 --- a/public/app/features/dashboard/components/PanelEditor/state/reducers.ts +++ b/public/app/features/dashboard/components/PanelEditor/state/reducers.ts @@ -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) => { state.getPanel = () => action.payload.panel; state.getSourcePanel = () => action.payload.sourcePanel; - state.querySubscription = action.payload.querySubscription; state.initDone = true; state.isOpen = true; state.shouldDiscardChanges = false; diff --git a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts index 15bf3d5c771..4e1def053dd 100644 --- a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts +++ b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts @@ -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(null); const [latestData, setLatestData] = useState(null); useEffect(() => { querySubscription.current = panel .getQueryRunner() - .getData() + .getData(options) .subscribe({ next: data => setLatestData(data), }); diff --git a/public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx b/public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx index 0e204ff01df..a4533a2790e 100644 --- a/public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx +++ b/public/app/features/dashboard/components/TransformationsEditor/TransformationsEditor.tsx @@ -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 { +interface State { + data?: DataFrame[]; +} + +export class TransformationsEditor extends React.PureComponent { + 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) => { const { transformations, onChange } = this.props; onChange([ @@ -84,8 +108,10 @@ export class TransformationsEditor extends React.PureComponent { }; renderTransformationEditors = () => { - const { transformations, dataFrames } = this.props; - const preTransformData = dataFrames; + const { transformations } = this.props; + const { data } = this.state; + + const preTransformData = data ?? []; return ( <> diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index a55c05d23d2..2f78c8a8b4b 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -70,7 +70,7 @@ export class PanelChrome extends PureComponent { } 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 { }, 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() { diff --git a/public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx b/public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx index 04b3d8fbbbe..5b902032b59 100644 --- a/public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx @@ -78,7 +78,9 @@ export class PanelChromeAngularUnconnected extends PureComponent { // 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), }); } diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 2e3f145d25b..b1f53ae8c5e 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -71,7 +71,7 @@ export class QueriesTab extends PureComponent { 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), }); diff --git a/public/app/features/dashboard/state/PanelQueryRunner.test.ts b/public/app/features/dashboard/state/PanelQueryRunner.test.ts index e4ad0e18956..65a4b95ba5a 100644 --- a/public/app/features/dashboard/state/PanelQueryRunner.test.ts +++ b/public/app/features/dashboard/state/PanelQueryRunner.test.ts @@ -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; }, diff --git a/public/app/features/dashboard/state/PanelQueryRunner.ts b/public/app/features/dashboard/state/PanelQueryRunner.ts index 1338112bb1f..b945acdce31 100644 --- a/public/app/features/dashboard/state/PanelQueryRunner.ts +++ b/public/app/features/dashboard/state/PanelQueryRunner.ts @@ -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; @@ -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 { + getData(options: GetDataOptions): Observable { const { withFieldConfig, withTransforms } = options; return this.subject.pipe( diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index ebdd02c9ccc..e543357af21 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -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() {