Merge branch 'piechart-react' of https://github.com/CorpGlory/grafana into CorpGlory-piechart-react

This commit is contained in:
Torkel Ödegaard
2019-03-20 19:01:37 +01:00
17 changed files with 682 additions and 2 deletions

View File

@@ -28,6 +28,7 @@ import * as singlestatPanel from 'app/plugins/panel/singlestat/module';
import * as singlestatPanel2 from 'app/plugins/panel/singlestat2/module';
import * as gettingStartedPanel from 'app/plugins/panel/gettingstarted/module';
import * as gaugePanel from 'app/plugins/panel/gauge/module';
import * as pieChartPanel from 'app/plugins/panel/piechart/module';
import * as barGaugePanel from 'app/plugins/panel/bargauge/module';
const builtInPlugins = {
@@ -61,6 +62,7 @@ const builtInPlugins = {
'app/plugins/panel/singlestat2/module': singlestatPanel2,
'app/plugins/panel/gettingstarted/module': gettingStartedPanel,
'app/plugins/panel/gauge/module': gaugePanel,
'app/plugins/panel/piechart/module': pieChartPanel,
'app/plugins/panel/bargauge/module': barGaugePanel,
};

View File

@@ -0,0 +1,47 @@
// Libraries
import React, { PureComponent } from 'react';
// Components
import { Select, FormLabel, PanelOptionsGroup } from '@grafana/ui';
// Types
import { FormField, PanelEditorProps } from '@grafana/ui';
import { PieChartType } from '@grafana/ui';
import { PieChartOptions } from './types';
const labelWidth = 8;
const pieChartOptions = [{ value: PieChartType.PIE, label: 'Pie' }, { value: PieChartType.DONUT, label: 'Donut' }];
export class PieChartOptionsBox extends PureComponent<PanelEditorProps<PieChartOptions>> {
onPieTypeChange = pieType => this.props.onOptionsChange({ ...this.props.options, pieType: pieType.value });
onStrokeWidthChange = ({ target }) =>
this.props.onOptionsChange({ ...this.props.options, strokeWidth: target.value });
render() {
const { options } = this.props;
const { pieType, strokeWidth } = options;
return (
<PanelOptionsGroup title="PieChart">
<div className="gf-form">
<FormLabel width={labelWidth}>Type</FormLabel>
<Select
width={12}
options={pieChartOptions}
onChange={this.onPieTypeChange}
value={pieChartOptions.find(option => option.value === pieType)}
/>
</div>
<div className="gf-form">
<FormField
label="Divider width"
labelWidth={labelWidth}
onChange={this.onStrokeWidthChange}
value={strokeWidth}
/>
</div>
</PanelOptionsGroup>
);
}
}

View File

@@ -0,0 +1,57 @@
// Libraries
import React, { PureComponent } from 'react';
// Services & Utils
import { processTimeSeries, ThemeContext } from '@grafana/ui';
// Components
import { PieChart, PieChartDataPoint } from '@grafana/ui';
// Types
import { PieChartOptions } from './types';
import { PanelProps, NullValueMode } from '@grafana/ui/src/types';
interface Props extends PanelProps<PieChartOptions> {}
export class PieChartPanel extends PureComponent<Props> {
render() {
const { panelData, width, height, options } = this.props;
const { valueOptions } = options;
const datapoints: PieChartDataPoint[] = [];
if (panelData.timeSeries) {
const vmSeries = processTimeSeries({
timeSeries: panelData.timeSeries,
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 (
<ThemeContext.Consumer>
{theme => (
<PieChart
width={width}
height={height}
datapoints={datapoints}
pieType={options.pieType}
strokeWidth={options.strokeWidth}
unit={valueOptions.unit}
theme={theme}
/>
)}
</ThemeContext.Consumer>
);
}
}

View File

@@ -0,0 +1,27 @@
import React, { PureComponent } from 'react';
import { PanelEditorProps, PanelOptionsGrid } from '@grafana/ui';
import PieChartValueEditor from './PieChartValueEditor';
import { PieChartOptionsBox } from './PieChartOptionsBox';
import { PieChartOptions, PieChartValueOptions } from './types';
export default class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChartOptions>> {
onValueOptionsChanged = (valueOptions: PieChartValueOptions) =>
this.props.onOptionsChange({
...this.props.options,
valueOptions,
});
render() {
const { onOptionsChange, options } = this.props;
return (
<>
<PanelOptionsGrid>
<PieChartValueEditor onChange={this.onValueOptionsChanged} options={options.valueOptions} />
<PieChartOptionsBox onOptionsChange={onOptionsChange} options={options} />
</PanelOptionsGrid>
</>
);
}
}

View File

@@ -0,0 +1,54 @@
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>
);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,10 @@
import { ReactPanelPlugin } from '@grafana/ui';
import PieChartPanelEditor from './PieChartPanelEditor';
import { PieChartPanel } from './PieChartPanel';
import { PieChartOptions, defaults } from './types';
export const reactPanel = new ReactPanelPlugin<PieChartOptions>(PieChartPanel);
reactPanel.setEditor(PieChartPanelEditor);
reactPanel.setDefaults(defaults);

View File

@@ -0,0 +1,19 @@
{
"type": "panel",
"name": "PieChart",
"id": "piechart",
"state": "alpha",
"dataFormats": ["time_series"],
"info": {
"author": {
"name": "Grafana Project",
"url": "https://grafana.com"
},
"logos": {
"small": "img/piechart_logo_small.png",
"large": "img/piechart_logo_large.png"
}
}
}

View File

@@ -0,0 +1,23 @@
import { PieChartType } from '@grafana/ui';
export interface PieChartOptions {
pieType: PieChartType;
strokeWidth: number;
valueOptions: PieChartValueOptions;
// TODO: Options for Legend / Combine components
}
export interface PieChartValueOptions {
unit: string;
stat: string;
}
export const defaults: PieChartOptions = {
pieType: PieChartType.PIE,
strokeWidth: 1,
valueOptions: {
unit: 'short',
stat: 'current',
},
};

View File

@@ -54,6 +54,7 @@
@import 'components/panel_alertlist';
@import 'components/panel_dashlist';
@import 'components/panel_gettingstarted';
@import 'components/panel_piechart';
@import 'components/panel_pluginlist';
@import 'components/panel_singlestat';
@import 'components/panel_table';

View File

@@ -0,0 +1,40 @@
.piechart-panel {
position: relative;
display: table;
width: 100%;
height: 100%;
.piechart-container {
top: 10px;
margin: auto;
svg {
width: 100%;
height: 100%;
}
}
.piechart-tooltip {
white-space: nowrap;
font-size: 12px;
background-color: #141414;
color: #d8d9da;
opacity: 0;
position: absolute;
.piechart-tooltip-time {
text-align: center;
position: relative;
padding: 0.2rem;
font-weight: bold;
color: #d8d9da;
.piechart-tooltip-value {
display: table-cell;
font-weight: bold;
padding: 15px;
text-align: right;
}
}
}
}