mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
graph: legend as React component
This commit is contained in:
parent
a702603e7b
commit
0e10fdb415
@ -6,6 +6,7 @@ import LoginBackground from './components/Login/LoginBackground';
|
||||
import { SearchResult } from './components/search/SearchResult';
|
||||
import { TagFilter } from './components/TagFilter/TagFilter';
|
||||
import DashboardPermissions from './components/Permissions/DashboardPermissions';
|
||||
import { GraphLegend } from 'app/plugins/panel/graph/Legend';
|
||||
|
||||
export function registerAngularDirectives() {
|
||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||
@ -19,4 +20,5 @@ export function registerAngularDirectives() {
|
||||
['tagOptions', { watchDepth: 'reference' }],
|
||||
]);
|
||||
react2AngularDirective('dashboardPermissions', DashboardPermissions, ['backendSrv', 'dashboardId', 'folder']);
|
||||
react2AngularDirective('graphLegendReact', GraphLegend, ['seriesList', 'className']);
|
||||
}
|
||||
|
189
public/app/plugins/panel/graph/Legend.tsx
Normal file
189
public/app/plugins/panel/graph/Legend.tsx
Normal file
@ -0,0 +1,189 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
|
||||
const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total'];
|
||||
|
||||
export interface GraphLegendProps {
|
||||
seriesList: any[];
|
||||
hiddenSeries: any;
|
||||
values?: boolean;
|
||||
min?: boolean;
|
||||
max?: boolean;
|
||||
avg?: boolean;
|
||||
current?: boolean;
|
||||
total?: boolean;
|
||||
alignAsTable?: boolean;
|
||||
rightSide?: boolean;
|
||||
sideWidth?: number;
|
||||
sort?: 'min' | 'max' | 'avg' | 'current' | 'total';
|
||||
sortDesc?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface GraphLegendState {}
|
||||
|
||||
export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLegendState> {
|
||||
sortLegend() {
|
||||
let seriesList = this.props.seriesList || [];
|
||||
if (this.props.sort) {
|
||||
seriesList = _.sortBy(seriesList, function(series) {
|
||||
let sort = series.stats[this.props.sort];
|
||||
if (sort === null) {
|
||||
sort = -Infinity;
|
||||
}
|
||||
return sort;
|
||||
});
|
||||
if (this.props.sortDesc) {
|
||||
seriesList = seriesList.reverse();
|
||||
}
|
||||
}
|
||||
return seriesList;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className = '', hiddenSeries } = this.props;
|
||||
const { values, min, max, avg, current, total } = this.props;
|
||||
const seriesValuesProps = { values, min, max, avg, current, total };
|
||||
const seriesList = this.sortLegend();
|
||||
return (
|
||||
<div className={`${className} graph-legend`}>
|
||||
<div className={`graph-legend-content ${this.props.alignAsTable ? 'graph-legend-table' : ''}`}>
|
||||
<div className="graph-legend-scroll">
|
||||
{this.props.alignAsTable ? (
|
||||
<LegendTable seriesList={seriesList} hiddenSeries={hiddenSeries} {...seriesValuesProps} />
|
||||
) : (
|
||||
seriesList.map((series, i) => (
|
||||
<LegendSeriesItem
|
||||
key={series.id}
|
||||
series={series}
|
||||
index={i}
|
||||
hiddenSeries={hiddenSeries}
|
||||
{...seriesValuesProps}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface LegendTableProps {
|
||||
seriesList: any[];
|
||||
hiddenSeries: any;
|
||||
values?: boolean;
|
||||
min?: boolean;
|
||||
max?: boolean;
|
||||
avg?: boolean;
|
||||
current?: boolean;
|
||||
total?: boolean;
|
||||
}
|
||||
|
||||
class LegendTable extends React.PureComponent<LegendTableProps> {
|
||||
render() {
|
||||
const seriesList = this.props.seriesList;
|
||||
const { values, min, max, avg, current, total } = this.props;
|
||||
const seriesValuesProps = { values, min, max, avg, current, total };
|
||||
const headerStyle: React.CSSProperties = {
|
||||
textAlign: 'left',
|
||||
};
|
||||
|
||||
return (
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colSpan={2} style={headerStyle} />
|
||||
{LEGEND_STATS.map(
|
||||
statName => seriesValuesProps[statName] && <LegendTableHeader key={statName} statName={statName} />
|
||||
)}
|
||||
</tr>
|
||||
{seriesList.map((series, i) => (
|
||||
<LegendSeriesItem
|
||||
key={series.id}
|
||||
series={series}
|
||||
index={i}
|
||||
hiddenSeries={this.props.hiddenSeries}
|
||||
{...seriesValuesProps}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface LegendTableHeaderProps {
|
||||
statName: string;
|
||||
sortDesc?: boolean;
|
||||
}
|
||||
|
||||
function LegendTableHeader(props: LegendTableHeaderProps) {
|
||||
return (
|
||||
<th className="pointer" data-stat={props.statName}>
|
||||
{props.statName}
|
||||
<span className={props.sortDesc ? 'fa fa-caret-down' : 'fa fa-caret-up'} />
|
||||
</th>
|
||||
);
|
||||
}
|
||||
|
||||
interface LegendSeriesItemProps {
|
||||
series: any;
|
||||
index: number;
|
||||
hiddenSeries: any;
|
||||
values?: boolean;
|
||||
min?: boolean;
|
||||
max?: boolean;
|
||||
avg?: boolean;
|
||||
current?: boolean;
|
||||
total?: boolean;
|
||||
}
|
||||
|
||||
class LegendSeriesItem extends React.Component<LegendSeriesItemProps> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { series, index, hiddenSeries } = this.props;
|
||||
const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries);
|
||||
const valueItems = this.props.values ? renderLegendValues(this.props, series) : [];
|
||||
return (
|
||||
<div className={`graph-legend-series ${seriesOptionClasses}`} data-series-index={index}>
|
||||
<div className="graph-legend-icon">
|
||||
<i className="fa fa-minus pointer" style={{ color: series.color }} />
|
||||
</div>
|
||||
<a className="graph-legend-alias pointer" title={series.aliasEscaped}>
|
||||
{series.aliasEscaped}
|
||||
</a>
|
||||
{valueItems}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function LegendValue(props) {
|
||||
const value = props.value;
|
||||
const valueName = props.valueName;
|
||||
return <div className={`graph-legend-value ${valueName}`}>{value}</div>;
|
||||
}
|
||||
|
||||
function renderLegendValues(props: LegendSeriesItemProps, series) {
|
||||
const legendValueItems = [];
|
||||
for (const valueName of LEGEND_STATS) {
|
||||
if (props[valueName]) {
|
||||
const valueFormatted = series.formatValue(series.stats[valueName]);
|
||||
legendValueItems.push(<LegendValue key={valueName} valueName={valueName} value={valueFormatted} />);
|
||||
}
|
||||
}
|
||||
return legendValueItems;
|
||||
}
|
||||
|
||||
function getOptionSeriesCSSClasses(series, hiddenSeries) {
|
||||
const classes = [];
|
||||
if (series.yaxis === 2) {
|
||||
classes.push('graph-legend-series--right-y');
|
||||
}
|
||||
if (hiddenSeries[series.alias]) {
|
||||
classes.push('graph-legend-series-hidden');
|
||||
}
|
||||
return classes.join(' ');
|
||||
}
|
@ -20,6 +20,9 @@ import { EventManager } from 'app/features/annotations/all';
|
||||
import { convertToHistogramData } from './histogram';
|
||||
import { alignYLevel } from './align_yaxes';
|
||||
import config from 'app/core/config';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { GraphLegend, GraphLegendProps } from './Legend';
|
||||
|
||||
import { GraphCtrl } from './module';
|
||||
|
||||
@ -82,7 +85,21 @@ class GraphElement {
|
||||
const graphHeight = this.elem.height();
|
||||
updateLegendValues(this.data, this.panel, graphHeight);
|
||||
|
||||
this.ctrl.events.emit('render-legend');
|
||||
// this.ctrl.events.emit('render-legend');
|
||||
const { values, min, max, avg, current, total } = this.panel.legend;
|
||||
const { alignAsTable, rightSide, sideWidth } = this.panel.legend;
|
||||
const legendOptions = { alignAsTable, rightSide, sideWidth };
|
||||
const valueOptions = { values, min, max, avg, current, total };
|
||||
const legendProps: GraphLegendProps = {
|
||||
seriesList: this.data,
|
||||
hiddenSeries: this.ctrl.hiddenSeries,
|
||||
...legendOptions,
|
||||
...valueOptions,
|
||||
};
|
||||
const legendReactElem = React.createElement(GraphLegend, legendProps);
|
||||
const legendElem = this.elem.parent().find('.graph-legend');
|
||||
ReactDOM.render(legendReactElem, legendElem[0]);
|
||||
this.onLegendRenderingComplete();
|
||||
}
|
||||
|
||||
onGraphHover(evt) {
|
||||
|
Loading…
Reference in New Issue
Block a user