mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
merge master
This commit is contained in:
commit
009cd086aa
@ -2,26 +2,20 @@ import React, { PureComponent } from 'react';
|
|||||||
import { select, pie, arc, event } from 'd3';
|
import { select, pie, arc, event } from 'd3';
|
||||||
import { sum } from 'lodash';
|
import { sum } from 'lodash';
|
||||||
|
|
||||||
import { GrafanaThemeType } from '../../types';
|
import { GrafanaThemeType, DisplayValue } from '../../types';
|
||||||
import { Themeable } from '../../index';
|
import { Themeable } from '../../index';
|
||||||
|
import { colors as grafana_colors } from '../../utils/index';
|
||||||
|
|
||||||
export enum PieChartType {
|
export enum PieChartType {
|
||||||
PIE = 'pie',
|
PIE = 'pie',
|
||||||
DONUT = 'donut',
|
DONUT = 'donut',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PieChartDataPoint {
|
|
||||||
value: number;
|
|
||||||
name: string;
|
|
||||||
color: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props extends Themeable {
|
export interface Props extends Themeable {
|
||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
datapoints: PieChartDataPoint[];
|
values: DisplayValue[];
|
||||||
|
|
||||||
unit: string;
|
|
||||||
pieType: PieChartType;
|
pieType: PieChartType;
|
||||||
strokeWidth: number;
|
strokeWidth: number;
|
||||||
}
|
}
|
||||||
@ -49,15 +43,20 @@ export class PieChart extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
const { datapoints, pieType, strokeWidth } = this.props;
|
const { values, pieType, strokeWidth } = this.props;
|
||||||
|
|
||||||
if (datapoints.length === 0) {
|
if (values.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = datapoints.map(datapoint => datapoint.value);
|
const data = values.map(datapoint => datapoint.numeric);
|
||||||
const names = datapoints.map(datapoint => datapoint.name);
|
const names = values.map(datapoint => datapoint.text);
|
||||||
const colors = datapoints.map(datapoint => datapoint.color);
|
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 total = sum(data) || 1;
|
||||||
const percents = data.map((item: number) => (item / total) * 100);
|
const percents = data.map((item: number) => (item / total) * 100);
|
||||||
@ -108,9 +107,9 @@ export class PieChart extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { height, width, datapoints } = this.props;
|
const { height, width, values } = this.props;
|
||||||
|
|
||||||
if (datapoints.length > 0) {
|
if (values.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div className="piechart-panel">
|
<div className="piechart-panel">
|
||||||
<div
|
<div
|
||||||
|
@ -25,7 +25,7 @@ export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid';
|
|||||||
export { ValueMappingsEditor } from './ValueMappingsEditor/ValueMappingsEditor';
|
export { ValueMappingsEditor } from './ValueMappingsEditor/ValueMappingsEditor';
|
||||||
export { Switch } from './Switch/Switch';
|
export { Switch } from './Switch/Switch';
|
||||||
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
|
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
|
||||||
export { PieChart, PieChartDataPoint, PieChartType } from './PieChart/PieChart';
|
export { PieChart, PieChartType } from './PieChart/PieChart';
|
||||||
export { UnitPicker } from './UnitPicker/UnitPicker';
|
export { UnitPicker } from './UnitPicker/UnitPicker';
|
||||||
export { StatsPicker } from './StatsPicker/StatsPicker';
|
export { StatsPicker } from './StatsPicker/StatsPicker';
|
||||||
export { Input, InputStatus } from './Input/Input';
|
export { Input, InputStatus } from './Input/Input';
|
||||||
|
@ -2,56 +2,34 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
// Services & Utils
|
// Services & Utils
|
||||||
import { processTimeSeries, ThemeContext } from '@grafana/ui';
|
import { config } from 'app/core/config';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { PieChart, PieChartDataPoint } from '@grafana/ui';
|
import { PieChart } from '@grafana/ui';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { PieChartOptions } from './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> {}
|
interface Props extends PanelProps<PieChartOptions> {}
|
||||||
|
|
||||||
export class PieChartPanel extends PureComponent<Props> {
|
export class PieChartPanel extends PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { data, width, height, options } = this.props;
|
const { width, height, options } = this.props;
|
||||||
const { valueOptions } = options;
|
|
||||||
|
|
||||||
const datapoints: PieChartDataPoint[] = [];
|
// TODO -- only process when the data/config changes
|
||||||
if (data) {
|
const values = getSingleStatValues(this.props);
|
||||||
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
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Consumer>
|
<PieChart
|
||||||
{theme => (
|
width={width}
|
||||||
<PieChart
|
height={height}
|
||||||
width={width}
|
values={values}
|
||||||
height={height}
|
pieType={options.pieType}
|
||||||
datapoints={datapoints}
|
strokeWidth={options.strokeWidth}
|
||||||
pieType={options.pieType}
|
theme={config.theme}
|
||||||
strokeWidth={options.strokeWidth}
|
/>
|
||||||
unit={valueOptions.unit}
|
|
||||||
theme={theme}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ThemeContext.Consumer>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import React, { PureComponent } from 'react';
|
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 { 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>> {
|
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.onOptionsChange({
|
||||||
...this.props.options,
|
...this.props.options,
|
||||||
valueOptions,
|
valueOptions,
|
||||||
@ -18,9 +25,11 @@ export default class PieChartPanelEditor extends PureComponent<PanelEditorProps<
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PanelOptionsGrid>
|
<PanelOptionsGrid>
|
||||||
<PieChartValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
<SingleStatValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
|
||||||
<PieChartOptionsBox onOptionsChange={onOptionsChange} options={options} />
|
<PieChartOptionsBox onOptionsChange={onOptionsChange} options={options} />
|
||||||
</PanelOptionsGrid>
|
</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,7 +3,9 @@ import { ReactPanelPlugin } from '@grafana/ui';
|
|||||||
import PieChartPanelEditor from './PieChartPanelEditor';
|
import PieChartPanelEditor from './PieChartPanelEditor';
|
||||||
import { PieChartPanel } from './PieChartPanel';
|
import { PieChartPanel } from './PieChartPanel';
|
||||||
import { PieChartOptions, defaults } from './types';
|
import { PieChartOptions, defaults } from './types';
|
||||||
|
import { singleStatBaseOptionsCheck } from '../singlestat2/module';
|
||||||
|
|
||||||
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel, defaults);
|
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel, defaults);
|
||||||
|
|
||||||
reactPanel.editor = PieChartPanelEditor;
|
reactPanel.editor = PieChartPanelEditor;
|
||||||
|
reactPanel.onPanelTypeChanged = 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;
|
pieType: PieChartType;
|
||||||
strokeWidth: number;
|
strokeWidth: number;
|
||||||
valueOptions: PieChartValueOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PieChartValueOptions {
|
|
||||||
unit: string;
|
|
||||||
stat: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaults: PieChartOptions = {
|
export const defaults: PieChartOptions = {
|
||||||
@ -16,6 +11,11 @@ export const defaults: PieChartOptions = {
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
valueOptions: {
|
valueOptions: {
|
||||||
unit: 'short',
|
unit: 'short',
|
||||||
stat: 'current',
|
stat: StatID.last,
|
||||||
|
suffix: '',
|
||||||
|
prefix: '',
|
||||||
},
|
},
|
||||||
|
valueMappings: [],
|
||||||
|
thresholds: [],
|
||||||
|
orientation: VizOrientation.Auto,
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@ export class SingleStatValueEditor extends PureComponent<Props> {
|
|||||||
return (
|
return (
|
||||||
<PanelOptionsGroup title="Value">
|
<PanelOptionsGroup title="Value">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<FormLabel width={labelWidth}>Stat</FormLabel>
|
<FormLabel width={labelWidth}>Show</FormLabel>
|
||||||
<StatsPicker
|
<StatsPicker
|
||||||
width={12}
|
width={12}
|
||||||
placeholder="Choose Stat"
|
placeholder="Choose Stat"
|
||||||
|
Loading…
Reference in New Issue
Block a user