mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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
This commit is contained in:
@@ -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> {
|
|||||||
</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> {
|
|||||||
{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> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
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 {
|
|||||||
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);
|
||||||
const getCounter = useCallback(
|
panel.on(CoreEvents.transformationChanged, this.triggerForceUpdate);
|
||||||
(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
componentWillUnmount() {
|
||||||
<div className={styles.wrapper}>
|
const { panel } = this.props;
|
||||||
<TabsBar className={styles.tabBar}>
|
panel.off(CoreEvents.queryChanged, this.triggerForceUpdate);
|
||||||
{tabs.map(tab => {
|
panel.off(CoreEvents.transformationChanged, this.triggerForceUpdate);
|
||||||
return (
|
}
|
||||||
<Tab
|
|
||||||
key={tab.id}
|
triggerForceUpdate = () => {
|
||||||
label={tab.text}
|
this.forceUpdate();
|
||||||
active={tab.active}
|
};
|
||||||
onChangeTab={() => onChangeTab(tab)}
|
|
||||||
icon={tab.icon as IconName}
|
getCounter = (tab: PanelEditorTab) => {
|
||||||
counter={getCounter(tab)}
|
const { panel } = this.props;
|
||||||
/>
|
|
||||||
);
|
switch (tab.id) {
|
||||||
})}
|
case PanelEditorTabId.Query:
|
||||||
</TabsBar>
|
return panel.targets.length;
|
||||||
<TabContent className={styles.tabContent}>
|
case PanelEditorTabId.Alert:
|
||||||
{activeTab.id === PanelEditorTabId.Query && <QueriesTab panel={panel} dashboard={dashboard} />}
|
return panel.alert ? 1 : 0;
|
||||||
{activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
|
case PanelEditorTabId.Transform:
|
||||||
{activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
|
const transformations = panel.getTransformations() ?? [];
|
||||||
</TabContent>
|
return transformations.length;
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
};
|
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 (
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<TabsBar className={styles.tabBar}>
|
||||||
|
{tabs.map(tab => {
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
key={tab.id}
|
||||||
|
label={tab.text}
|
||||||
|
active={tab.active}
|
||||||
|
onChangeTab={() => onChangeTab(tab)}
|
||||||
|
icon={tab.icon as IconName}
|
||||||
|
counter={this.getCounter(tab)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TabsBar>
|
||||||
|
<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} />}
|
||||||
|
</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> {
|
|||||||
* 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';
|
|||||||
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';
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
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');
|
|||||||
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');
|
||||||
|
|||||||
Reference in New Issue
Block a user