Commit 244c2875 by Peter Holmberg Committed by GitHub

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
parent 33663657
...@@ -142,7 +142,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> { ...@@ -142,7 +142,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
document.body.style.cursor = 'row-resize'; document.body.style.cursor = 'row-resize';
}; };
onDiplayModeChange = (mode: DisplayMode) => { onDisplayModeChange = (mode: DisplayMode) => {
const { updatePanelEditorUIState } = this.props; const { updatePanelEditorUIState } = this.props;
updatePanelEditorUIState({ updatePanelEditorUIState({
mode: mode, mode: mode,
...@@ -184,6 +184,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> { ...@@ -184,6 +184,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
</div> </div>
); );
}; };
renderHorizontalSplit(styles: EditorStyles) { renderHorizontalSplit(styles: EditorStyles) {
const { dashboard, panel, tabs, uiState } = this.props; const { dashboard, panel, tabs, uiState } = this.props;
return tabs.length > 0 ? ( return tabs.length > 0 ? (
...@@ -230,7 +231,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> { ...@@ -230,7 +231,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
{this.renderTemplateVariables(styles)} {this.renderTemplateVariables(styles)}
<HorizontalGroup> <HorizontalGroup>
<RadioButtonGroup value={uiState.mode} options={displayModes} onChange={this.onDiplayModeChange} /> <RadioButtonGroup value={uiState.mode} options={displayModes} onChange={this.onDisplayModeChange} />
<DashNavTimeControls <DashNavTimeControls
dashboard={dashboard} dashboard={dashboard}
location={location} location={location}
...@@ -348,7 +349,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> { ...@@ -348,7 +349,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
} }
} }
const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, props) => { const mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = state => {
const panel = state.panelEditor.getPanel(); const panel = state.panelEditor.getPanel();
const { plugin } = getPanelStateById(state.dashboard, panel.id); const { plugin } = getPanelStateById(state.dashboard, panel.id);
......
import React, { useCallback } from 'react'; import React, { PureComponent } from 'react';
import { config } from 'app/core/config'; import { config } from 'app/core/config';
import { css } from 'emotion'; import { css } from 'emotion';
import { IconName, stylesFactory, Tab, TabContent, TabsBar } from '@grafana/ui'; 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 { QueriesTab } from '../../panel_editor/QueriesTab';
import { PanelModel } from '../../state/PanelModel';
import { AlertTab } from 'app/features/alerting/AlertTab'; import { AlertTab } from 'app/features/alerting/AlertTab';
import { TransformationsEditor } from '../TransformationsEditor/TransformationsEditor'; import { TransformationsEditor } from '../TransformationsEditor/TransformationsEditor';
import { DashboardModel, PanelModel } from '../../state';
import { CoreEvents } from 'app/types';
import { PanelEditorTab, PanelEditorTabId } from './types';
interface PanelEditorTabsProps { interface PanelEditorTabsProps {
panel: PanelModel; panel: PanelModel;
...@@ -16,55 +16,73 @@ interface PanelEditorTabsProps { ...@@ -16,55 +16,73 @@ interface PanelEditorTabsProps {
onChangeTab: (tab: PanelEditorTab) => void; onChangeTab: (tab: PanelEditorTab) => void;
} }
export const PanelEditorTabs: React.FC<PanelEditorTabsProps> = ({ panel, dashboard, tabs, onChangeTab }) => { export class PanelEditorTabs extends PureComponent<PanelEditorTabsProps> {
const styles = getPanelEditorTabsStyles(); componentDidMount() {
const activeTab = tabs.find(item => item.active)!; const { panel } = this.props;
panel.on(CoreEvents.queryChanged, this.triggerForceUpdate);
panel.on(CoreEvents.transformationChanged, this.triggerForceUpdate);
}
const getCounter = useCallback( componentWillUnmount() {
(tab: PanelEditorTab) => { const { panel } = this.props;
switch (tab.id) { panel.off(CoreEvents.queryChanged, this.triggerForceUpdate);
case PanelEditorTabId.Query: panel.off(CoreEvents.transformationChanged, this.triggerForceUpdate);
return panel.targets.length; }
case PanelEditorTabId.Alert:
return panel.alert ? 1 : 0;
case PanelEditorTabId.Transform:
const transformations = panel.getTransformations() ?? [];
return transformations.length;
}
return null; triggerForceUpdate = () => {
}, this.forceUpdate();
[panel] };
);
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;
}
if (tabs.length === 0) {
return null; return null;
} };
render() {
const { dashboard, onChangeTab, tabs, panel } = this.props;
const styles = getPanelEditorTabsStyles();
const activeTab = tabs.find(item => item.active)!;
return ( if (tabs.length === 0) {
<div className={styles.wrapper}> return null;
<TabsBar className={styles.tabBar}> }
{tabs.map(tab => {
return ( return (
<Tab <div className={styles.wrapper}>
key={tab.id} <TabsBar className={styles.tabBar}>
label={tab.text} {tabs.map(tab => {
active={tab.active} return (
onChangeTab={() => onChangeTab(tab)} <Tab
icon={tab.icon as IconName} key={tab.id}
counter={getCounter(tab)} label={tab.text}
/> active={tab.active}
); onChangeTab={() => onChangeTab(tab)}
})} icon={tab.icon as IconName}
</TabsBar> counter={this.getCounter(tab)}
<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 panel={panel} />} </TabsBar>
</TabContent> <TabContent className={styles.tabContent}>
</div> {activeTab.id === PanelEditorTabId.Query && <QueriesTab panel={panel} dashboard={dashboard} />}
); {activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
}; {activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
</TabContent>
</div>
);
}
}
const getPanelEditorTabsStyles = stylesFactory(() => { const getPanelEditorTabsStyles = stylesFactory(() => {
const { theme } = config; const { theme } = config;
......
...@@ -161,7 +161,9 @@ export class QueriesTab extends PureComponent<Props, State> { ...@@ -161,7 +161,9 @@ export class QueriesTab extends PureComponent<Props, State> {
* Sets the queries for the panel * Sets the queries for the panel
*/ */
onUpdateQueries = (queries: DataQuery[]) => { onUpdateQueries = (queries: DataQuery[]) => {
this.props.panel.targets = queries; this.props.panel.updateQueries(queries);
// Need to force update to rerender query rows.
this.forceUpdate(); this.forceUpdate();
}; };
......
...@@ -6,6 +6,7 @@ import { getNextRefIdChar } from 'app/core/utils/query'; ...@@ -6,6 +6,7 @@ import { getNextRefIdChar } from 'app/core/utils/query';
import templateSrv from 'app/features/templating/template_srv'; import templateSrv from 'app/features/templating/template_srv';
// Types // Types
import { import {
AppEvent,
DataConfigSource, DataConfigSource,
DataLink, DataLink,
DataQuery, DataQuery,
...@@ -23,6 +24,7 @@ import { EDIT_PANEL_ID } from 'app/core/constants'; ...@@ -23,6 +24,7 @@ import { EDIT_PANEL_ID } from 'app/core/constants';
import config from 'app/core/config'; import config from 'app/core/config';
import { PanelQueryRunner } from './PanelQueryRunner'; import { PanelQueryRunner } from './PanelQueryRunner';
import { getDatasourceSrv } from '../../plugins/datasource_srv'; import { getDatasourceSrv } from '../../plugins/datasource_srv';
import { CoreEvents } from '../../../types';
export const panelAdded = eventFactory<PanelModel | undefined>('panel-added'); export const panelAdded = eventFactory<PanelModel | undefined>('panel-added');
export const panelRemoved = eventFactory<PanelModel | undefined>('panel-removed'); export const panelRemoved = eventFactory<PanelModel | undefined>('panel-removed');
...@@ -382,6 +384,11 @@ export class PanelModel implements DataConfigSource { ...@@ -382,6 +384,11 @@ export class PanelModel implements DataConfigSource {
} }
} }
updateQueries(queries: DataQuery[]) {
this.events.emit(CoreEvents.queryChanged);
this.targets = queries;
}
addQuery(query?: Partial<DataQuery>) { addQuery(query?: Partial<DataQuery>) {
query = query || { refId: 'A' }; query = query || { refId: 'A' };
query.refId = getNextRefIdChar(this.targets); query.refId = getNextRefIdChar(this.targets);
...@@ -461,6 +468,7 @@ export class PanelModel implements DataConfigSource { ...@@ -461,6 +468,7 @@ export class PanelModel implements DataConfigSource {
} }
setTransformations(transformations: DataTransformerConfig[]) { setTransformations(transformations: DataTransformerConfig[]) {
this.events.emit(CoreEvents.transformationChanged);
this.transformations = transformations; this.transformations = transformations;
this.resendLastResult(); this.resendLastResult();
} }
...@@ -488,6 +496,14 @@ export class PanelModel implements DataConfigSource { ...@@ -488,6 +496,14 @@ export class PanelModel implements DataConfigSource {
getSavedId(): number { getSavedId(): number {
return this.editSourceId ?? this.id; return this.editSourceId ?? this.id;
} }
on<T>(event: AppEvent<T>, callback: (payload?: T) => void) {
this.events.on(event, callback);
}
off<T>(event: AppEvent<T>, callback: (payload?: T) => void) {
this.events.off(event, callback);
}
} }
function applyFieldConfigDefaults(fieldConfig: FieldConfigSource, defaults: FieldConfigSource): FieldConfigSource { function applyFieldConfigDefaults(fieldConfig: FieldConfigSource, defaults: FieldConfigSource): FieldConfigSource {
......
...@@ -156,3 +156,6 @@ export const jsonDiffReady = eventFactory('json-diff-ready'); ...@@ -156,3 +156,6 @@ export const jsonDiffReady = eventFactory('json-diff-ready');
export const closeTimepicker = eventFactory('closeTimepicker'); export const closeTimepicker = eventFactory('closeTimepicker');
export const routeUpdated = eventFactory('$routeUpdate'); export const routeUpdated = eventFactory('$routeUpdate');
export const queryChanged = eventFactory('queryChanged');
export const transformationChanged = eventFactory('transformationChanged');
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment