mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 20:24:18 -06:00
use display value in pie chart
This commit is contained in:
parent
0f0f76b602
commit
2e079659f8
@ -2,26 +2,20 @@ import React, { PureComponent } from 'react';
|
||||
import { select, pie, arc, event } from 'd3';
|
||||
import { sum } from 'lodash';
|
||||
|
||||
import { GrafanaThemeType } from '../../types';
|
||||
import { GrafanaThemeType, DisplayValue } from '../../types';
|
||||
import { Themeable } from '../../index';
|
||||
import { colors as grafana_colors } from '../../utils/index';
|
||||
|
||||
export enum PieChartType {
|
||||
PIE = 'pie',
|
||||
DONUT = 'donut',
|
||||
}
|
||||
|
||||
export interface PieChartDataPoint {
|
||||
value: number;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface Props extends Themeable {
|
||||
height: number;
|
||||
width: number;
|
||||
datapoints: PieChartDataPoint[];
|
||||
values: DisplayValue[];
|
||||
|
||||
unit: string;
|
||||
pieType: PieChartType;
|
||||
strokeWidth: number;
|
||||
}
|
||||
@ -49,15 +43,20 @@ export class PieChart extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
draw() {
|
||||
const { datapoints, pieType, strokeWidth } = this.props;
|
||||
const { values, pieType, strokeWidth } = this.props;
|
||||
|
||||
if (datapoints.length === 0) {
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = datapoints.map(datapoint => datapoint.value);
|
||||
const names = datapoints.map(datapoint => datapoint.name);
|
||||
const colors = datapoints.map(datapoint => datapoint.color);
|
||||
const data = values.map(datapoint => datapoint.numeric);
|
||||
const names = values.map(datapoint => datapoint.text);
|
||||
const colors = values.map((p, idx) => {
|
||||
if (p.color) {
|
||||
return p.color;
|
||||
}
|
||||
return grafana_colors[idx % grafana_colors.length];
|
||||
});
|
||||
|
||||
const total = sum(data) || 1;
|
||||
const percents = data.map((item: number) => (item / total) * 100);
|
||||
@ -108,9 +107,9 @@ export class PieChart extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { height, width, datapoints } = this.props;
|
||||
const { height, width, values } = this.props;
|
||||
|
||||
if (datapoints.length > 0) {
|
||||
if (values.length > 0) {
|
||||
return (
|
||||
<div className="piechart-panel">
|
||||
<div
|
||||
|
@ -25,7 +25,7 @@ export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid';
|
||||
export { ValueMappingsEditor } from './ValueMappingsEditor/ValueMappingsEditor';
|
||||
export { Switch } from './Switch/Switch';
|
||||
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
|
||||
export { PieChart, PieChartDataPoint, PieChartType } from './PieChart/PieChart';
|
||||
export { PieChart, PieChartType } from './PieChart/PieChart';
|
||||
export { UnitPicker } from './UnitPicker/UnitPicker';
|
||||
export { StatsPicker } from './StatsPicker/StatsPicker';
|
||||
export { Input, InputStatus } from './Input/Input';
|
||||
|
@ -2,56 +2,34 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
// Services & Utils
|
||||
import { processTimeSeries, ThemeContext } from '@grafana/ui';
|
||||
import { config } from 'app/core/config';
|
||||
|
||||
// Components
|
||||
import { PieChart, PieChartDataPoint } from '@grafana/ui';
|
||||
import { PieChart } from '@grafana/ui';
|
||||
|
||||
// Types
|
||||
import { PieChartOptions } from './types';
|
||||
import { PanelProps, NullValueMode } from '@grafana/ui/src/types';
|
||||
import { PanelProps } from '@grafana/ui/src/types';
|
||||
import { getSingleStatValues } from '../singlestat2/SingleStatPanel';
|
||||
|
||||
interface Props extends PanelProps<PieChartOptions> {}
|
||||
|
||||
export class PieChartPanel extends PureComponent<Props> {
|
||||
render() {
|
||||
const { data, width, height, options } = this.props;
|
||||
const { valueOptions } = options;
|
||||
const { width, height, options } = this.props;
|
||||
|
||||
const datapoints: PieChartDataPoint[] = [];
|
||||
if (data) {
|
||||
const vmSeries = processTimeSeries({
|
||||
data,
|
||||
nullValueMode: NullValueMode.Null,
|
||||
});
|
||||
|
||||
for (let i = 0; i < vmSeries.length; i++) {
|
||||
const serie = vmSeries[i];
|
||||
if (serie) {
|
||||
datapoints.push({
|
||||
value: serie.stats[valueOptions.stat],
|
||||
name: serie.label,
|
||||
color: serie.color,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: support table data
|
||||
// TODO -- only process when the data/config changes
|
||||
const values = getSingleStatValues(this.props);
|
||||
|
||||
return (
|
||||
<ThemeContext.Consumer>
|
||||
{theme => (
|
||||
<PieChart
|
||||
width={width}
|
||||
height={height}
|
||||
datapoints={datapoints}
|
||||
pieType={options.pieType}
|
||||
strokeWidth={options.strokeWidth}
|
||||
unit={valueOptions.unit}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
</ThemeContext.Consumer>
|
||||
<PieChart
|
||||
width={width}
|
||||
height={height}
|
||||
values={values}
|
||||
pieType={options.pieType}
|
||||
strokeWidth={options.strokeWidth}
|
||||
theme={config.theme}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,19 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { PanelEditorProps, PanelOptionsGrid } from '@grafana/ui';
|
||||
import { PanelEditorProps, PanelOptionsGrid, ValueMappingsEditor, ValueMapping } from '@grafana/ui';
|
||||
|
||||
import PieChartValueEditor from './PieChartValueEditor';
|
||||
import { PieChartOptionsBox } from './PieChartOptionsBox';
|
||||
import { PieChartOptions, PieChartValueOptions } from './types';
|
||||
import { PieChartOptions } from './types';
|
||||
import { SingleStatValueEditor } from '../singlestat2/SingleStatValueEditor';
|
||||
import { SingleStatValueOptions } from '../singlestat2/types';
|
||||
|
||||
export default class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChartOptions>> {
|
||||
onValueOptionsChanged = (valueOptions: PieChartValueOptions) =>
|
||||
onValueMappingsChanged = (valueMappings: ValueMapping[]) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
valueMappings,
|
||||
});
|
||||
|
||||
onValueOptionsChanged = (valueOptions: SingleStatValueOptions) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
valueOptions,
|
||||
@ -18,9 +25,11 @@ export default class PieChartPanelEditor extends PureComponent<PanelEditorProps<
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<PieChartValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
||||
<SingleStatValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
||||
<PieChartOptionsBox onOptionsChange={onOptionsChange} options={options} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { FormLabel, PanelOptionsGroup, Select, UnitPicker } from '@grafana/ui';
|
||||
import { PieChartValueOptions } from './types';
|
||||
|
||||
const statOptions = [
|
||||
{ value: 'min', label: 'Min' },
|
||||
{ value: 'max', label: 'Max' },
|
||||
{ value: 'avg', label: 'Average' },
|
||||
{ value: 'current', label: 'Current' },
|
||||
{ value: 'total', label: 'Total' },
|
||||
];
|
||||
|
||||
const labelWidth = 6;
|
||||
|
||||
export interface Props {
|
||||
options: PieChartValueOptions;
|
||||
onChange: (valueOptions: PieChartValueOptions) => void;
|
||||
}
|
||||
|
||||
export default class PieChartValueEditor extends PureComponent<Props> {
|
||||
onUnitChange = unit =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
unit: unit.value,
|
||||
});
|
||||
|
||||
onStatChange = stat =>
|
||||
this.props.onChange({
|
||||
...this.props.options,
|
||||
stat: stat.value,
|
||||
});
|
||||
|
||||
render() {
|
||||
const { stat, unit } = this.props.options;
|
||||
|
||||
return (
|
||||
<PanelOptionsGroup title="Value">
|
||||
<div className="gf-form">
|
||||
<FormLabel width={labelWidth}>Unit</FormLabel>
|
||||
<UnitPicker defaultValue={unit} onChange={this.onUnitChange} />
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormLabel width={labelWidth}>Value</FormLabel>
|
||||
<Select
|
||||
width={12}
|
||||
options={statOptions}
|
||||
onChange={this.onStatChange}
|
||||
value={statOptions.find(option => option.value === stat)}
|
||||
/>
|
||||
</div>
|
||||
</PanelOptionsGroup>
|
||||
);
|
||||
}
|
||||
}
|
@ -3,8 +3,10 @@ import { ReactPanelPlugin } from '@grafana/ui';
|
||||
import PieChartPanelEditor from './PieChartPanelEditor';
|
||||
import { PieChartPanel } from './PieChartPanel';
|
||||
import { PieChartOptions, defaults } from './types';
|
||||
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
||||
|
||||
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel);
|
||||
|
||||
reactPanel.setEditor(PieChartPanelEditor);
|
||||
reactPanel.setDefaults(defaults);
|
||||
reactPanel.setPanelTypeChangedHook(singleStatBaseOptionsCheck);
|
||||
|
@ -1,14 +1,9 @@
|
||||
import { PieChartType } from '@grafana/ui';
|
||||
import { PieChartType, StatID, VizOrientation } from '@grafana/ui';
|
||||
import { SingleStatBaseOptions } from '../singlestat2/types';
|
||||
|
||||
export interface PieChartOptions {
|
||||
export interface PieChartOptions extends SingleStatBaseOptions {
|
||||
pieType: PieChartType;
|
||||
strokeWidth: number;
|
||||
valueOptions: PieChartValueOptions;
|
||||
}
|
||||
|
||||
export interface PieChartValueOptions {
|
||||
unit: string;
|
||||
stat: string;
|
||||
}
|
||||
|
||||
export const defaults: PieChartOptions = {
|
||||
@ -16,6 +11,11 @@ export const defaults: PieChartOptions = {
|
||||
strokeWidth: 1,
|
||||
valueOptions: {
|
||||
unit: 'short',
|
||||
stat: 'current',
|
||||
stat: StatID.last,
|
||||
suffix: '',
|
||||
prefix: '',
|
||||
},
|
||||
valueMappings: [],
|
||||
thresholds: [],
|
||||
orientation: VizOrientation.Auto,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user