mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #14811 from grafana/move-threshold-component-to-ui-components
Moved Thresholds and styles to grafana/ui/components
This commit is contained in:
commit
f5ae40cf54
@ -1,23 +1,18 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import Thresholds from './Thresholds';
|
||||
import { defaultProps } from './GaugePanelOptions';
|
||||
import { BasicGaugeColor } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
import { ThresholdsEditor, Props } from './ThresholdsEditor';
|
||||
import { BasicGaugeColor } from '../../types';
|
||||
|
||||
const setup = (propOverrides?: object) => {
|
||||
const props: PanelOptionsProps<Options> = {
|
||||
const props: Props = {
|
||||
onChange: jest.fn(),
|
||||
options: {
|
||||
...defaultProps.options,
|
||||
thresholds: [],
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(props, propOverrides);
|
||||
|
||||
return shallow(<Thresholds {...props} />).instance() as Thresholds;
|
||||
return shallow(<ThresholdsEditor {...props} />).instance() as ThresholdsEditor;
|
||||
};
|
||||
|
||||
describe('Add threshold', () => {
|
||||
@ -31,10 +26,7 @@ describe('Add threshold', () => {
|
||||
|
||||
it('should add another threshold above a first', () => {
|
||||
const instance = setup({
|
||||
options: {
|
||||
...defaultProps.options,
|
||||
thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }],
|
||||
},
|
||||
});
|
||||
|
||||
instance.onAddThreshold(1);
|
@ -1,32 +1,37 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { ColorPicker } from '@grafana/ui';
|
||||
import { BasicGaugeColor, Threshold } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
import tinycolor, { ColorInput } from 'tinycolor2';
|
||||
|
||||
import { Threshold, BasicGaugeColor } from '../../types';
|
||||
import { ColorPicker } from '../ColorPicker/ColorPicker';
|
||||
|
||||
export interface Props {
|
||||
thresholds: Threshold[];
|
||||
onChange: (thresholds: Threshold[]) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
thresholds: Threshold[];
|
||||
baseColor: string;
|
||||
}
|
||||
|
||||
export default class Thresholds extends PureComponent<PanelOptionsProps<Options>, State> {
|
||||
constructor(props) {
|
||||
export class ThresholdsEditor extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
thresholds: props.options.thresholds,
|
||||
baseColor: props.options.baseColor,
|
||||
};
|
||||
this.state = { thresholds: props.thresholds, baseColor: BasicGaugeColor.Green };
|
||||
}
|
||||
|
||||
onAddThreshold = index => {
|
||||
const { maxValue, minValue } = this.props.options;
|
||||
onAddThreshold = (index: number) => {
|
||||
const maxValue = 100; // hardcoded for now before we add the base threshold
|
||||
const minValue = 0; // hardcoded for now before we add the base threshold
|
||||
const { thresholds } = this.state;
|
||||
|
||||
const newThresholds = thresholds.map(threshold => {
|
||||
if (threshold.index >= index) {
|
||||
threshold = { ...threshold, index: threshold.index + 1 };
|
||||
threshold = {
|
||||
...threshold,
|
||||
index: threshold.index + 1,
|
||||
};
|
||||
}
|
||||
|
||||
return threshold;
|
||||
@ -48,27 +53,32 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
|
||||
if (index === 0 && thresholds.length === 0) {
|
||||
color = tinycolor.mix(BasicGaugeColor.Green, BasicGaugeColor.Red, 50).toRgbString();
|
||||
} else {
|
||||
color = tinycolor.mix(thresholds[index - 1].color, BasicGaugeColor.Red, 50).toRgbString();
|
||||
color = tinycolor.mix(thresholds[index - 1].color as ColorInput, BasicGaugeColor.Red, 50).toRgbString();
|
||||
}
|
||||
|
||||
this.setState(
|
||||
{
|
||||
thresholds: this.sortThresholds([...newThresholds, { index: index, value: value, color: color }]),
|
||||
thresholds: this.sortThresholds([
|
||||
...newThresholds,
|
||||
{
|
||||
index,
|
||||
value: value as number,
|
||||
color,
|
||||
},
|
||||
]),
|
||||
},
|
||||
() => this.updateGauge()
|
||||
);
|
||||
};
|
||||
|
||||
onRemoveThreshold = threshold => {
|
||||
onRemoveThreshold = (threshold: Threshold) => {
|
||||
this.setState(
|
||||
prevState => ({
|
||||
thresholds: prevState.thresholds.filter(t => t !== threshold),
|
||||
}),
|
||||
prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold) }),
|
||||
() => this.updateGauge()
|
||||
);
|
||||
};
|
||||
|
||||
onChangeThresholdValue = (event, threshold) => {
|
||||
onChangeThresholdValue = (event: any, threshold: Threshold) => {
|
||||
const { thresholds } = this.state;
|
||||
|
||||
const newThresholds = thresholds.map(t => {
|
||||
@ -79,12 +89,10 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
|
||||
return t;
|
||||
});
|
||||
|
||||
this.setState({
|
||||
thresholds: newThresholds,
|
||||
});
|
||||
this.setState({ thresholds: newThresholds });
|
||||
};
|
||||
|
||||
onChangeThresholdColor = (threshold, color) => {
|
||||
onChangeThresholdColor = (threshold: Threshold, color: string) => {
|
||||
const { thresholds } = this.state;
|
||||
|
||||
const newThresholds = thresholds.map(t => {
|
||||
@ -103,20 +111,18 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
|
||||
);
|
||||
};
|
||||
|
||||
onChangeBaseColor = color => this.props.onChange({ ...this.props.options, baseColor: color });
|
||||
onChangeBaseColor = (color: string) => this.props.onChange(this.state.thresholds);
|
||||
onBlur = () => {
|
||||
this.setState(prevState => ({
|
||||
thresholds: this.sortThresholds(prevState.thresholds),
|
||||
}));
|
||||
this.setState(prevState => ({ thresholds: this.sortThresholds(prevState.thresholds) }));
|
||||
|
||||
this.updateGauge();
|
||||
};
|
||||
|
||||
updateGauge = () => {
|
||||
this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds });
|
||||
this.props.onChange(this.state.thresholds);
|
||||
};
|
||||
|
||||
sortThresholds = thresholds => {
|
||||
sortThresholds = (thresholds: Threshold[]) => {
|
||||
return thresholds.sort((t1, t2) => {
|
||||
return t2.value - t1.value;
|
||||
});
|
||||
@ -161,20 +167,8 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
|
||||
return thresholds.map((t, i) => {
|
||||
return (
|
||||
<div key={`${t.value}-${i}`} className="indicator-section">
|
||||
<div
|
||||
onClick={() => this.onAddThreshold(t.index + 1)}
|
||||
style={{
|
||||
height: '50%',
|
||||
backgroundColor: t.color,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
onClick={() => this.onAddThreshold(t.index)}
|
||||
style={{
|
||||
height: '50%',
|
||||
backgroundColor: t.color,
|
||||
}}
|
||||
/>
|
||||
<div onClick={() => this.onAddThreshold(t.index + 1)} style={{ height: '50%', backgroundColor: t.color }} />
|
||||
<div onClick={() => this.onAddThreshold(t.index)} style={{ height: '50%', backgroundColor: t.color }} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@ -185,14 +179,14 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
|
||||
<div className="indicator-section" style={{ height: '100%' }}>
|
||||
<div
|
||||
onClick={() => this.onAddThreshold(0)}
|
||||
style={{ height: '100%', backgroundColor: this.props.options.baseColor }}
|
||||
style={{ height: '100%', backgroundColor: BasicGaugeColor.Green }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderBase() {
|
||||
const { baseColor } = this.props.options;
|
||||
const baseColor = BasicGaugeColor.Green;
|
||||
|
||||
return (
|
||||
<div className="threshold-row threshold-row-base">
|
@ -1,4 +1,5 @@
|
||||
@import 'CustomScrollbar/CustomScrollbar';
|
||||
@import 'DeleteButton/DeleteButton';
|
||||
@import 'ThresholdsEditor/ThresholdsEditor';
|
||||
@import 'Tooltip/Tooltip';
|
||||
@import 'Select/Select';
|
||||
|
@ -13,3 +13,4 @@ export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
|
||||
export { ColorPicker } from './ColorPicker/ColorPicker';
|
||||
export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
|
||||
export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker';
|
||||
export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { RangeMap, ValueMap, Threshold } from 'app/types';
|
||||
import { RangeMap, Threshold, ValueMap } from './panel';
|
||||
|
||||
export interface Options {
|
||||
export interface GaugeOptions {
|
||||
baseColor: string;
|
||||
decimals: number;
|
||||
mappings: Array<RangeMap | ValueMap>;
|
@ -1,3 +1,4 @@
|
||||
export * from './series';
|
||||
export * from './time';
|
||||
export * from './panel';
|
||||
export * from './gauge';
|
||||
|
@ -29,3 +29,35 @@ export interface PanelMenuItem {
|
||||
shortcut?: string;
|
||||
subMenu?: PanelMenuItem[];
|
||||
}
|
||||
|
||||
export interface Threshold {
|
||||
index: number;
|
||||
value: number;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export enum BasicGaugeColor {
|
||||
Green = '#299c46',
|
||||
Red = '#d44a3a',
|
||||
}
|
||||
|
||||
export enum MappingType {
|
||||
ValueToText = 1,
|
||||
RangeToText = 2,
|
||||
}
|
||||
|
||||
interface BaseMap {
|
||||
id: number;
|
||||
operator: string;
|
||||
text: string;
|
||||
type: MappingType;
|
||||
}
|
||||
|
||||
export interface ValueMap extends BaseMap {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface RangeMap extends BaseMap {
|
||||
from: string;
|
||||
to: string;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { GaugeOptions, PanelOptionsProps } from '@grafana/ui';
|
||||
|
||||
import { Switch } from 'app/core/components/Switch/Switch';
|
||||
import { Label } from '../../../core/components/Label/Label';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
export default class GaugeOptions extends PureComponent<PanelOptionsProps<Options>> {
|
||||
export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
onToggleThresholdLabels = () =>
|
||||
this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelProps, NullValueMode } from '@grafana/ui';
|
||||
import { GaugeOptions, PanelProps, NullValueMode } from '@grafana/ui';
|
||||
|
||||
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
|
||||
import Gauge from 'app/viz/Gauge';
|
||||
import { Options } from './types';
|
||||
|
||||
interface Props extends PanelProps<Options> {}
|
||||
interface Props extends PanelProps<GaugeOptions> {}
|
||||
|
||||
export class GaugePanel extends PureComponent<Props> {
|
||||
render() {
|
||||
|
@ -1,11 +1,9 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { BasicGaugeColor, GaugeOptions, PanelOptionsProps, ThresholdsEditor, Threshold } from '@grafana/ui';
|
||||
|
||||
import ValueOptions from 'app/plugins/panel/gauge/ValueOptions';
|
||||
import Thresholds from 'app/plugins/panel/gauge/Thresholds';
|
||||
import { BasicGaugeColor } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import ValueMappings from 'app/plugins/panel/gauge/ValueMappings';
|
||||
import { Options } from './types';
|
||||
import GaugeOptions from './GaugeOptions';
|
||||
import GaugeOptionsEditor from './GaugeOptionsEditor';
|
||||
|
||||
export const defaultProps = {
|
||||
options: {
|
||||
@ -24,17 +22,19 @@ export const defaultProps = {
|
||||
},
|
||||
};
|
||||
|
||||
export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<Options>> {
|
||||
export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
static defaultProps = defaultProps;
|
||||
|
||||
onThresholdsChanged = (thresholds: Threshold[]) => this.props.onChange({ ...this.props.options, thresholds });
|
||||
|
||||
render() {
|
||||
const { onChange, options } = this.props;
|
||||
return (
|
||||
<>
|
||||
<div className="form-section">
|
||||
<ValueOptions onChange={onChange} options={options} />
|
||||
<GaugeOptions onChange={onChange} options={options} />
|
||||
<Thresholds onChange={onChange} options={options} />
|
||||
<GaugeOptionsEditor onChange={onChange} options={options} />
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
|
||||
</div>
|
||||
|
||||
<div className="form-section">
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { MappingType, RangeMap, Select, ValueMap } from '@grafana/ui';
|
||||
|
||||
import { Label } from 'app/core/components/Label/Label';
|
||||
import { Select } from '@grafana/ui';
|
||||
import { MappingType, RangeMap, ValueMap } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
mapping: ValueMap | RangeMap;
|
||||
|
@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import ValueMappings from './ValueMappings';
|
||||
import { MappingType } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui';
|
||||
import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions';
|
||||
|
||||
import ValueMappings from './ValueMappings';
|
||||
|
||||
const setup = (propOverrides?: object) => {
|
||||
const props: PanelOptionsProps<Options> = {
|
||||
const props: PanelOptionsProps<GaugeOptions> = {
|
||||
onChange: jest.fn(),
|
||||
options: {
|
||||
...defaultProps.options,
|
||||
|
@ -1,15 +1,14 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { GaugeOptions, PanelOptionsProps, MappingType, RangeMap, ValueMap } from '@grafana/ui';
|
||||
|
||||
import MappingRow from './MappingRow';
|
||||
import { MappingType, RangeMap, ValueMap } from 'app/types';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
interface State {
|
||||
mappings: Array<ValueMap | RangeMap>;
|
||||
nextIdToAdd: number;
|
||||
}
|
||||
|
||||
export default class ValueMappings extends PureComponent<PanelOptionsProps<Options>, State> {
|
||||
export default class ValueMappings extends PureComponent<PanelOptionsProps<GaugeOptions>, State> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { GaugeOptions, PanelOptionsProps } from '@grafana/ui';
|
||||
|
||||
import { Label } from 'app/core/components/Label/Label';
|
||||
import { Select} from '@grafana/ui';
|
||||
import UnitPicker from 'app/core/components/Select/UnitPicker';
|
||||
import { PanelOptionsProps } from '@grafana/ui';
|
||||
import { Options } from './types';
|
||||
|
||||
const statOptions = [
|
||||
{ value: 'min', label: 'Min' },
|
||||
@ -21,7 +21,7 @@ const statOptions = [
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export default class ValueOptions extends PureComponent<PanelOptionsProps<Options>> {
|
||||
export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
|
||||
onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
|
||||
|
||||
onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });
|
||||
|
@ -9,7 +9,6 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
|
||||
import { Invitee, OrgUser, User, UsersState, UserState } from './user';
|
||||
import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources';
|
||||
import { DataQuery, DataQueryResponse, DataQueryOptions } from './series';
|
||||
import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from './panel';
|
||||
import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins';
|
||||
import { Organization, OrganizationState } from './organization';
|
||||
import {
|
||||
@ -69,13 +68,8 @@ export {
|
||||
AppNotificationTimeout,
|
||||
DashboardSearchHit,
|
||||
UserState,
|
||||
Threshold,
|
||||
ValidationEvents,
|
||||
ValidationRule,
|
||||
ValueMap,
|
||||
RangeMap,
|
||||
MappingType,
|
||||
BasicGaugeColor,
|
||||
};
|
||||
|
||||
export interface StoreState {
|
||||
|
@ -1,31 +0,0 @@
|
||||
export interface Threshold {
|
||||
index: number;
|
||||
value: number;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export enum MappingType {
|
||||
ValueToText = 1,
|
||||
RangeToText = 2,
|
||||
}
|
||||
|
||||
export enum BasicGaugeColor {
|
||||
Green = '#299c46',
|
||||
Red = '#d44a3a',
|
||||
}
|
||||
|
||||
interface BaseMap {
|
||||
id: number;
|
||||
operator: string;
|
||||
text: string;
|
||||
type: MappingType;
|
||||
}
|
||||
|
||||
export interface ValueMap extends BaseMap {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface RangeMap extends BaseMap {
|
||||
from: string;
|
||||
to: string;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { BasicGaugeColor, TimeSeriesVMs } from '@grafana/ui';
|
||||
|
||||
import { Gauge, Props } from './Gauge';
|
||||
import { BasicGaugeColor } from '../types';
|
||||
import { TimeSeriesVMs } from '@grafana/ui';
|
||||
|
||||
jest.mock('jquery', () => ({
|
||||
plot: jest.fn(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import $ from 'jquery';
|
||||
import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from 'app/types';
|
||||
import { TimeSeriesVMs } from '@grafana/ui';
|
||||
import { BasicGaugeColor, Threshold, TimeSeriesVMs, RangeMap, ValueMap, MappingType } from '@grafana/ui';
|
||||
|
||||
import config from '../core/config';
|
||||
import kbn from '../core/utils/kbn';
|
||||
|
||||
|
@ -98,7 +98,6 @@
|
||||
@import 'components/toolbar';
|
||||
@import 'components/add_data_source.scss';
|
||||
@import 'components/page_loader';
|
||||
@import 'components/thresholds';
|
||||
@import 'components/toggle_button_group';
|
||||
@import 'components/value-mappings';
|
||||
@import 'components/popover-box';
|
||||
|
Loading…
Reference in New Issue
Block a user