Commit f5ae40cf by Hugo Häggmark Committed by GitHub

Merge pull request #14811 from grafana/move-threshold-component-to-ui-components

Moved Thresholds and styles to grafana/ui/components
parents bc78c8d5 d97cd450
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: [],
},
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)' }],
},
thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }],
});
instance.onAddThreshold(1);
......
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">
......
@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';
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>;
......
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;
}
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 });
......
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() {
......
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">
......
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;
......
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,
......
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);
......
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 {
......
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;
}
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(),
......
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';
......
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