From 244c28750cb5a8a788beb0badab6e9abba8e8eb7 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 28 Sep 2020 09:06:46 +0200 Subject: [PATCH] Fix: Update badges on PanelEditor tabs when adding a query/transformation/alert (#27729) * minor nits in paneleditor * add events for queries and transformations * fix spelling * add event to alertctrl * revert alert changes * re add force update * reduce events --- .../components/PanelEditor/PanelEditor.tsx | 7 +- .../PanelEditor/PanelEditorTabs.tsx | 120 ++++++++++-------- .../dashboard/panel_editor/QueriesTab.tsx | 4 +- .../features/dashboard/state/PanelModel.ts | 16 +++ public/app/types/events.ts | 3 + 5 files changed, 95 insertions(+), 55 deletions(-) diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index b7ea9b45c3f..4b8312a8268 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -142,7 +142,7 @@ export class PanelEditorUnconnected extends PureComponent { document.body.style.cursor = 'row-resize'; }; - onDiplayModeChange = (mode: DisplayMode) => { + onDisplayModeChange = (mode: DisplayMode) => { const { updatePanelEditorUIState } = this.props; updatePanelEditorUIState({ mode: mode, @@ -184,6 +184,7 @@ export class PanelEditorUnconnected extends PureComponent { ); }; + renderHorizontalSplit(styles: EditorStyles) { const { dashboard, panel, tabs, uiState } = this.props; return tabs.length > 0 ? ( @@ -230,7 +231,7 @@ export class PanelEditorUnconnected extends PureComponent { {this.renderTemplateVariables(styles)} - + { } } -const mapStateToProps: MapStateToProps = (state, props) => { +const mapStateToProps: MapStateToProps = state => { const panel = state.panelEditor.getPanel(); const { plugin } = getPanelStateById(state.dashboard, panel.id); diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx index 2d17bee9804..bdf6c3dfafb 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx @@ -1,13 +1,13 @@ -import React, { useCallback } from 'react'; +import React, { PureComponent } from 'react'; import { config } from 'app/core/config'; import { css } from 'emotion'; import { IconName, stylesFactory, Tab, TabContent, TabsBar } from '@grafana/ui'; -import { PanelEditorTab, PanelEditorTabId } from './types'; -import { DashboardModel } from '../../state'; import { QueriesTab } from '../../panel_editor/QueriesTab'; -import { PanelModel } from '../../state/PanelModel'; import { AlertTab } from 'app/features/alerting/AlertTab'; import { TransformationsEditor } from '../TransformationsEditor/TransformationsEditor'; +import { DashboardModel, PanelModel } from '../../state'; +import { CoreEvents } from 'app/types'; +import { PanelEditorTab, PanelEditorTabId } from './types'; interface PanelEditorTabsProps { panel: PanelModel; @@ -16,55 +16,73 @@ interface PanelEditorTabsProps { onChangeTab: (tab: PanelEditorTab) => void; } -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) { - case PanelEditorTabId.Query: - return panel.targets.length; - case PanelEditorTabId.Alert: - return panel.alert ? 1 : 0; - case PanelEditorTabId.Transform: - const transformations = panel.getTransformations() ?? []; - return transformations.length; - } - - return null; - }, - [panel] - ); - - if (tabs.length === 0) { - return null; +export class PanelEditorTabs extends PureComponent { + componentDidMount() { + const { panel } = this.props; + panel.on(CoreEvents.queryChanged, this.triggerForceUpdate); + panel.on(CoreEvents.transformationChanged, this.triggerForceUpdate); } - return ( -
- - {tabs.map(tab => { - return ( - onChangeTab(tab)} - icon={tab.icon as IconName} - counter={getCounter(tab)} - /> - ); - })} - - - {activeTab.id === PanelEditorTabId.Query && } - {activeTab.id === PanelEditorTabId.Alert && } - {activeTab.id === PanelEditorTabId.Transform && } - -
- ); -}; + componentWillUnmount() { + const { panel } = this.props; + panel.off(CoreEvents.queryChanged, this.triggerForceUpdate); + panel.off(CoreEvents.transformationChanged, this.triggerForceUpdate); + } + + triggerForceUpdate = () => { + this.forceUpdate(); + }; + + getCounter = (tab: PanelEditorTab) => { + const { panel } = this.props; + + switch (tab.id) { + case PanelEditorTabId.Query: + return panel.targets.length; + case PanelEditorTabId.Alert: + return panel.alert ? 1 : 0; + case PanelEditorTabId.Transform: + const transformations = panel.getTransformations() ?? []; + return transformations.length; + } + + return null; + }; + + render() { + const { dashboard, onChangeTab, tabs, panel } = this.props; + const styles = getPanelEditorTabsStyles(); + const activeTab = tabs.find(item => item.active)!; + + if (tabs.length === 0) { + return null; + } + + return ( +
+ + {tabs.map(tab => { + return ( + onChangeTab(tab)} + icon={tab.icon as IconName} + counter={this.getCounter(tab)} + /> + ); + })} + + + {activeTab.id === PanelEditorTabId.Query && } + {activeTab.id === PanelEditorTabId.Alert && } + {activeTab.id === PanelEditorTabId.Transform && } + +
+ ); + } +} const getPanelEditorTabsStyles = stylesFactory(() => { const { theme } = config; diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 6e2859cc3a6..99434812939 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -161,7 +161,9 @@ export class QueriesTab extends PureComponent { * Sets the queries for the panel */ onUpdateQueries = (queries: DataQuery[]) => { - this.props.panel.targets = queries; + this.props.panel.updateQueries(queries); + + // Need to force update to rerender query rows. this.forceUpdate(); }; diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index ff8698c3768..ae94ab78967 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -6,6 +6,7 @@ import { getNextRefIdChar } from 'app/core/utils/query'; import templateSrv from 'app/features/templating/template_srv'; // Types import { + AppEvent, DataConfigSource, DataLink, DataQuery, @@ -23,6 +24,7 @@ import { EDIT_PANEL_ID } from 'app/core/constants'; import config from 'app/core/config'; import { PanelQueryRunner } from './PanelQueryRunner'; import { getDatasourceSrv } from '../../plugins/datasource_srv'; +import { CoreEvents } from '../../../types'; export const panelAdded = eventFactory('panel-added'); export const panelRemoved = eventFactory('panel-removed'); @@ -382,6 +384,11 @@ export class PanelModel implements DataConfigSource { } } + updateQueries(queries: DataQuery[]) { + this.events.emit(CoreEvents.queryChanged); + this.targets = queries; + } + addQuery(query?: Partial) { query = query || { refId: 'A' }; query.refId = getNextRefIdChar(this.targets); @@ -461,6 +468,7 @@ export class PanelModel implements DataConfigSource { } setTransformations(transformations: DataTransformerConfig[]) { + this.events.emit(CoreEvents.transformationChanged); this.transformations = transformations; this.resendLastResult(); } @@ -488,6 +496,14 @@ export class PanelModel implements DataConfigSource { getSavedId(): number { return this.editSourceId ?? this.id; } + + on(event: AppEvent, callback: (payload?: T) => void) { + this.events.on(event, callback); + } + + off(event: AppEvent, callback: (payload?: T) => void) { + this.events.off(event, callback); + } } function applyFieldConfigDefaults(fieldConfig: FieldConfigSource, defaults: FieldConfigSource): FieldConfigSource { diff --git a/public/app/types/events.ts b/public/app/types/events.ts index c35e01ce422..20edb6294bc 100644 --- a/public/app/types/events.ts +++ b/public/app/types/events.ts @@ -156,3 +156,6 @@ export const jsonDiffReady = eventFactory('json-diff-ready'); export const closeTimepicker = eventFactory('closeTimepicker'); export const routeUpdated = eventFactory('$routeUpdate'); + +export const queryChanged = eventFactory('queryChanged'); +export const transformationChanged = eventFactory('transformationChanged');