mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PanelEditorTabs: Fixes theme and update issues when queries change from outside (#32204)
* PanelEditorTabs: Fixes theme and update issues when queries change from outside * Remove unnessary arrow function * Removed setState
This commit is contained in:
parent
49a5b9f0cb
commit
ca8295e298
@ -5,6 +5,7 @@ export * from './dataLinks';
|
||||
export * from './tags';
|
||||
export * from './scrollbar';
|
||||
export * from './measureText';
|
||||
export * from './useForceUpdate';
|
||||
export { default as ansicolor } from './ansicolor';
|
||||
|
||||
import * as DOMUtil from './dom'; // includes Element.closest polyfill
|
||||
|
7
packages/grafana-ui/src/utils/useForceUpdate.ts
Normal file
7
packages/grafana-ui/src/utils/useForceUpdate.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
/** @internal */
|
||||
export function useForceUpdate() {
|
||||
const [value, setValue] = useState(0); // integer state
|
||||
return () => setValue(value + 1); // update the state to force render
|
||||
}
|
@ -3,23 +3,21 @@ import { QueryGroup } from 'app/features/query/components/QueryGroup';
|
||||
import { PanelModel } from '../../state';
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
import { QueryGroupOptions } from 'app/types';
|
||||
import { DataQuery } from '@grafana/data';
|
||||
|
||||
interface Props {
|
||||
/** Current panel */
|
||||
panel: PanelModel;
|
||||
/** Added here to make component re-render when queries change from outside */
|
||||
queries: DataQuery[];
|
||||
}
|
||||
|
||||
interface State {
|
||||
options: QueryGroupOptions;
|
||||
}
|
||||
|
||||
export class PanelEditorQueries extends PureComponent<Props, State> {
|
||||
export class PanelEditorQueries extends PureComponent<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = { options: this.buildQueryOptions(props) };
|
||||
}
|
||||
|
||||
buildQueryOptions({ panel }: Props): QueryGroupOptions {
|
||||
buildQueryOptions(panel: PanelModel): QueryGroupOptions {
|
||||
return {
|
||||
dataSource: {
|
||||
name: panel.datasource,
|
||||
@ -51,20 +49,17 @@ export class PanelEditorQueries extends PureComponent<Props, State> {
|
||||
|
||||
const newDataSourceName = options.dataSource.default ? null : options.dataSource.name!;
|
||||
const dataSourceChanged = newDataSourceName !== panel.datasource;
|
||||
|
||||
panel.updateQueries(options);
|
||||
|
||||
if (dataSourceChanged) {
|
||||
// trigger queries when changing data source
|
||||
setTimeout(this.onRunQueries, 10);
|
||||
}
|
||||
|
||||
this.setState({ options: options });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { panel } = this.props;
|
||||
const { options } = this.state;
|
||||
const options = this.buildQueryOptions(panel);
|
||||
|
||||
return (
|
||||
<QueryGroup
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { config } from 'app/core/config';
|
||||
import React, { FC, useEffect } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { IconName, stylesFactory, Tab, TabContent, TabsBar } from '@grafana/ui';
|
||||
import { IconName, Tab, TabContent, TabsBar, useForceUpdate, useStyles } from '@grafana/ui';
|
||||
import { AlertTab } from 'app/features/alerting/AlertTab';
|
||||
import { TransformationsEditor } from '../TransformationsEditor/TransformationsEditor';
|
||||
import { DashboardModel, PanelModel } from '../../state';
|
||||
@ -9,6 +8,7 @@ import { PanelEditorTab, PanelEditorTabId } from './types';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { PanelQueriesChangedEvent, PanelTransformationsChangedEvent } from 'app/types/events';
|
||||
import { PanelEditorQueries } from './PanelEditorQueries';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
|
||||
interface PanelEditorTabsProps {
|
||||
panel: PanelModel;
|
||||
@ -17,77 +17,65 @@ interface PanelEditorTabsProps {
|
||||
onChangeTab: (tab: PanelEditorTab) => void;
|
||||
}
|
||||
|
||||
export class PanelEditorTabs extends PureComponent<PanelEditorTabsProps> {
|
||||
private eventSubs = new Subscription();
|
||||
export const PanelEditorTabs: FC<PanelEditorTabsProps> = React.memo(({ panel, dashboard, tabs, onChangeTab }) => {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const styles = useStyles(getStyles);
|
||||
|
||||
componentDidMount() {
|
||||
const { events } = this.props.panel;
|
||||
this.eventSubs.add(events.subscribe(PanelQueriesChangedEvent, this.triggerForceUpdate));
|
||||
this.eventSubs.add(events.subscribe(PanelTransformationsChangedEvent, this.triggerForceUpdate));
|
||||
}
|
||||
useEffect(() => {
|
||||
const eventSubs = new Subscription();
|
||||
eventSubs.add(panel.events.subscribe(PanelQueriesChangedEvent, forceUpdate));
|
||||
eventSubs.add(panel.events.subscribe(PanelTransformationsChangedEvent, forceUpdate));
|
||||
return () => eventSubs.unsubscribe();
|
||||
}, [panel, forceUpdate]);
|
||||
|
||||
componentWillUnmount() {
|
||||
this.eventSubs.unsubscribe();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const activeTab = tabs.find((item) => item.active)!;
|
||||
|
||||
if (tabs.length === 0) {
|
||||
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 && <PanelEditorQueries panel={panel} />}
|
||||
{activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
|
||||
{activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
|
||||
</TabContent>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
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={getCounter(panel, tab)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TabsBar>
|
||||
<TabContent className={styles.tabContent}>
|
||||
{activeTab.id === PanelEditorTabId.Query && <PanelEditorQueries panel={panel} queries={panel.targets} />}
|
||||
{activeTab.id === PanelEditorTabId.Alert && <AlertTab panel={panel} dashboard={dashboard} />}
|
||||
{activeTab.id === PanelEditorTabId.Transform && <TransformationsEditor panel={panel} />}
|
||||
</TabContent>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
PanelEditorTabs.displayName = 'PanelEditorTabs';
|
||||
|
||||
function getCounter(panel: PanelModel, 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;
|
||||
}
|
||||
|
||||
const getPanelEditorTabsStyles = stylesFactory(() => {
|
||||
const { theme } = config;
|
||||
|
||||
const getStyles = (theme: GrafanaTheme) => {
|
||||
return {
|
||||
wrapper: css`
|
||||
display: flex;
|
||||
@ -111,4 +99,4 @@ const getPanelEditorTabsStyles = stylesFactory(() => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user