Commit d38a0a0b by Torkel Ödegaard Committed by GitHub

Merge pull request #14106 from grafana/unit-picker

Unit picker
parents 2dc44f60 638c04e1
import React, { PureComponent } from 'react';
import { GroupProps } from 'react-select/lib/components/Group';
interface ExtendedGroupProps extends GroupProps<any> {
data: any;
}
interface State {
expanded: boolean;
}
export default class UnitGroup extends PureComponent<ExtendedGroupProps, State> {
state = {
expanded: false,
};
componentDidUpdate(nextProps) {
if (nextProps.selectProps.inputValue !== '') {
this.setState({ expanded: true });
}
}
onToggleChildren = () => {
this.setState(prevState => ({
expanded: !prevState.expanded,
}));
};
render() {
const { children, label } = this.props;
const { expanded } = this.state;
return (
<div className="width-21 unit-picker-group" style={{ marginBottom: '5px' }}>
<div className="unit-picker-group-item" onClick={this.onToggleChildren}>
<span style={{ textTransform: 'capitalize' }}>{label}</span>
<i className={`fa ${expanded ? 'fa-minus' : 'fa-plus'}`} />{' '}
</div>
{expanded && children}
</div>
);
}
}
import React, { SFC } from 'react';
import { components } from 'react-select';
import { OptionProps } from 'react-select/lib/components/Option';
interface ExtendedOptionProps extends OptionProps<any> {
data: any;
}
const UnitOption: SFC<ExtendedOptionProps> = props => {
const { children, isSelected, className } = props;
return (
<components.Option {...props}>
<div className={`unit-picker-option__button btn btn-link ${className}`}>
{isSelected && <i className="fa fa-check pull-right" aria-hidden="true" />}
<div className="gf-form">{children}</div>
</div>
</components.Option>
);
};
export default UnitOption;
import React, { PureComponent } from 'react';
import Select from 'react-select';
import UnitGroup from './UnitGroup';
import UnitOption from './UnitOption';
import ResetStyles from '../ResetStyles';
import kbn from '../../../utils/kbn';
interface Props {
onSelected: (item: any) => {} | void;
defaultValue?: string;
}
export default class UnitPicker extends PureComponent<Props> {
render() {
const { defaultValue, onSelected } = this.props;
const unitGroups = kbn.getUnitFormats();
// Need to transform the data structure to work well with Select
const groupOptions = unitGroups.map(group => {
const options = group.submenu.map(unit => {
return {
label: unit.text,
value: unit.value,
};
});
return {
label: group.text,
options,
};
});
const styles = {
...ResetStyles,
menu: () => ({
maxHeight: '75%',
overflow: 'scroll',
}),
menuList: () =>
({
overflowY: 'auto',
position: 'relative',
} as React.CSSProperties),
};
const value = groupOptions.map(group => {
return group.options.find(option => option.value === defaultValue);
});
return (
<Select
classNamePrefix="gf-form-select-box"
className="width-20 gf-form-input--form-dropdown"
defaultValue={value}
isSearchable={true}
menuShouldScrollIntoView={false}
options={groupOptions}
placeholder="Choose"
onChange={onSelected}
components={{
Group: UnitGroup,
Option: UnitOption,
}}
styles={styles}
/>
);
}
}
......@@ -405,7 +405,8 @@ kbn.valueFormats.percentunit = (size, decimals) => {
};
/* Formats the value to hex. Uses float if specified decimals are not 0.
* There are two options, one with 0x, and one without */
* There are two submenu
* , one with 0x, and one without */
kbn.valueFormats.hex = (value, decimals) => {
if (value == null) {
......
......@@ -134,6 +134,7 @@ export class DataPanel extends Component<Props, State> {
render() {
const { queries } = this.props;
const { response, loading, isFirstLoad } = this.state;
const timeSeries = response.data;
if (isFirstLoad && loading === LoadingState.Loading) {
......
......@@ -70,7 +70,6 @@ export class PanelChrome extends PureComponent<Props, State> {
};
onRender = () => {
console.log('onRender');
this.setState({
renderCounter: this.state.renderCounter + 1,
});
......@@ -87,7 +86,6 @@ export class PanelChrome extends PureComponent<Props, State> {
const { datasource, targets } = panel;
const PanelComponent = this.props.component;
console.log('panelChrome render');
return (
<AutoSizer>
{({ width, height }) => {
......
......@@ -28,13 +28,15 @@ export class ElasticConfigCtrl {
];
indexPatternTypeChanged() {
if (!this.current.database ||
this.current.database.length === 0 ||
this.current.database.startsWith('[logstash-]')) {
const def = _.find(this.indexPatternTypes, {
value: this.current.jsonData.interval,
});
this.current.database = def.example || 'es-index-name';
if (
!this.current.database ||
this.current.database.length === 0 ||
this.current.database.startsWith('[logstash-]')
) {
const def = _.find(this.indexPatternTypes, {
value: this.current.jsonData.interval,
});
this.current.database = def.example || 'es-index-name';
}
}
}
import React, { PureComponent } from 'react';
import Gauge from 'app/viz/Gauge';
import { NullValueMode, PanelProps } from 'app/types';
import { Label } from 'app/core/components/Label/Label';
import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker';
import { NullValueMode, PanelOptionsProps, PanelProps } from 'app/types';
import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
import { GaugeOptions } from './GaugeOptions';
export interface Options {}
export interface Options {
unit: { label: string; value: string };
}
interface Props extends PanelProps<Options> {}
export class GaugePanel extends PureComponent<Props> {
render() {
const { timeSeries, width, height } = this.props;
const { unit } = this.props.options;
const vmSeries = getTimeSeriesVMs({
timeSeries: timeSeries,
......@@ -18,7 +22,35 @@ export class GaugePanel extends PureComponent<Props> {
});
return (
<Gauge maxValue={100} minValue={0} timeSeries={vmSeries} thresholds={[0, 100]} height={height} width={width} />
<Gauge
maxValue={100}
minValue={0}
timeSeries={vmSeries}
thresholds={[0, 100]}
height={height}
width={width}
unit={unit}
/>
);
}
}
export class GaugeOptions extends PureComponent<PanelOptionsProps<Options>> {
onUnitChange = value => {
this.props.onChange({ ...this.props.options, unit: value });
};
render() {
return (
<div>
<div className="section gf-form-group">
<h5 className="page-heading">Value</h5>
<div className="gf-form-inline">
<Label width={5}>Unit</Label>
<UnitPicker defaultValue={this.props.options.unit.value} onSelected={value => this.onUnitChange(value)} />
</div>
</div>
</div>
);
}
}
......
......@@ -2,6 +2,7 @@ import React, { PureComponent } from 'react';
import $ from 'jquery';
import { TimeSeriesVMs } from 'app/types';
import config from '../core/config';
import kbn from '../core/utils/kbn';
interface Props {
timeSeries: TimeSeriesVMs;
......@@ -10,6 +11,7 @@ interface Props {
showThresholdMarkers?: boolean;
thresholds?: number[];
showThresholdLables?: boolean;
unit: { label: string; value: string };
width: number;
height: number;
}
......@@ -36,6 +38,13 @@ export class Gauge extends PureComponent<Props> {
this.draw();
}
formatValue(value) {
const { unit } = this.props;
const formatFunc = kbn.valueFormats[unit.value];
return formatFunc(value);
}
draw() {
const {
maxValue,
......@@ -94,7 +103,7 @@ export class Gauge extends PureComponent<Props> {
value: {
color: fontColor,
formatter: () => {
return Math.round(timeSeries[0].stats.avg);
return this.formatValue(timeSeries[0].stats.avg);
},
font: {
size: fontSize,
......
......@@ -102,6 +102,7 @@
@import 'components/delete_button';
@import 'components/add_data_source.scss';
@import 'components/page_loader';
@import 'components/unit-picker';
// PAGES
@import 'pages/login';
......
.unit-picker-option {
position: relative;
width: 100%;
display: block;
border-radius: 0;
white-space: normal;
i.fa-check {
padding-left: 2px;
}
}
.unit-picker-group {
margin-bottom: 5px;
}
.unit-picker-group-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
font-size: 14px;
border-bottom: 1px solid #555;
}
......@@ -397,15 +397,7 @@
dependencies:
"@types/react" "*"
"@types/react@*":
version "16.4.16"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.16.tgz#99f91b1200ae8c2062030402006d3b3c3a177043"
integrity sha512-lxyoipLWweAnLnSsV4Ho2NAZTKKmxeYgkTQ6PaDiPDU9JJBUY2zJVVGiK1smzYv8+ZgbqEmcm5xM74GCpunSEA==
dependencies:
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/react@^16.1.0", "@types/react@^16.7.6":
"@types/react@*", "@types/react@16.7.6", "@types/react@^16.1.0", "@types/react@^16.7.6":
version "16.7.6"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040"
integrity sha512-QBUfzftr/8eg/q3ZRgf/GaDP6rTYc7ZNem+g4oZM38C9vXyV8AWRWaTQuW5yCoZTsfHrN7b3DeEiUnqH9SrnpA==
......
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