Files
grafana/public/app/plugins/panel/graph/Legend/Legend.tsx

225 lines
6.7 KiB
TypeScript
Raw Normal View History

2018-08-31 13:24:49 +03:00
import _ from 'lodash';
import React from 'react';
2018-09-03 16:54:52 +03:00
import { TimeSeries } from 'app/core/core';
import CustomScrollbar from 'app/core/components/CustomScrollbar/CustomScrollbar';
2018-10-17 15:07:31 +03:00
import { LegendItem, LEGEND_STATS } from './LegendSeriesItem';
2018-08-31 13:24:49 +03:00
2018-09-03 16:54:52 +03:00
interface LegendProps {
seriesList: TimeSeries[];
optionalClass?: string;
onToggleSeries?: (series: TimeSeries, event: Event) => void;
onToggleSort?: (sortBy, sortDesc) => void;
2018-10-17 15:07:31 +03:00
onToggleAxis?: (series: TimeSeries) => void;
2018-10-16 16:50:43 +03:00
onColorChange?: (series: TimeSeries, color: string) => void;
2018-09-03 16:54:52 +03:00
}
interface LegendDisplayProps {
2018-08-31 13:24:49 +03:00
hiddenSeries: any;
2018-09-03 16:54:52 +03:00
hideEmpty?: boolean;
hideZero?: boolean;
alignAsTable?: boolean;
rightSide?: boolean;
sideWidth?: number;
}
interface LegendValuesProps {
2018-08-31 13:24:49 +03:00
values?: boolean;
min?: boolean;
max?: boolean;
avg?: boolean;
current?: boolean;
total?: boolean;
2018-09-03 16:54:52 +03:00
}
interface LegendSortProps {
2018-08-31 13:24:49 +03:00
sort?: 'min' | 'max' | 'avg' | 'current' | 'total';
sortDesc?: boolean;
}
2018-09-03 16:54:52 +03:00
export type GraphLegendProps = LegendProps & LegendDisplayProps & LegendValuesProps & LegendSortProps;
2018-10-17 15:07:31 +03:00
export class GraphLegend extends React.PureComponent<GraphLegendProps> {
static defaultProps: Partial<GraphLegendProps> = {
values: false,
min: false,
max: false,
avg: false,
current: false,
total: false,
alignAsTable: false,
rightSide: false,
sort: undefined,
sortDesc: false,
optionalClass: '',
onToggleSeries: () => {},
onToggleSort: () => {},
onToggleAxis: () => {},
onColorChange: () => {},
};
2018-09-03 16:54:52 +03:00
2018-08-31 13:24:49 +03:00
sortLegend() {
let seriesList = this.props.seriesList || [];
if (this.props.sort) {
2018-09-03 16:54:52 +03:00
seriesList = _.sortBy(seriesList, series => {
2018-08-31 13:24:49 +03:00
let sort = series.stats[this.props.sort];
if (sort === null) {
sort = -Infinity;
}
return sort;
});
if (this.props.sortDesc) {
seriesList = seriesList.reverse();
}
}
return seriesList;
}
onToggleSeries(series: TimeSeries, event: Event) {
// const scrollPosition = legendScrollbar.scroller.scrollTop;
this.props.onToggleSeries(series, event);
// legendScrollbar.scroller.scrollTop = scrollPosition;
}
2018-08-31 13:24:49 +03:00
render() {
const { optionalClass, hiddenSeries, rightSide, sideWidth, sort, sortDesc, hideEmpty, hideZero } = this.props;
2018-08-31 13:24:49 +03:00
const { values, min, max, avg, current, total } = this.props;
const seriesValuesProps = { values, min, max, avg, current, total };
2018-09-03 16:54:52 +03:00
const seriesHideProps = { hideEmpty, hideZero };
const sortProps = { sort, sortDesc };
2018-09-03 16:54:52 +03:00
const seriesList = _.filter(this.sortLegend(), series => !series.hideFromLegend(seriesHideProps));
const legendClass = `${this.props.alignAsTable ? 'graph-legend-table' : ''} ${optionalClass}`;
2018-08-31 17:27:57 +03:00
// Set min-width if side style and there is a value, otherwise remove the CSS property
// Set width so it works with IE11
const width: any = rightSide && sideWidth ? sideWidth : undefined;
const ieWidth: any = rightSide && sideWidth ? sideWidth - 1 : undefined;
const legendStyle: React.CSSProperties = {
2018-08-31 17:27:57 +03:00
minWidth: width,
width: ieWidth,
2018-08-31 13:24:49 +03:00
};
const legendProps: GraphLegendProps = {
seriesList: seriesList,
hiddenSeries: hiddenSeries,
onToggleSeries: (s, e) => this.onToggleSeries(s, e),
onToggleSort: (sortBy, sortDesc) => this.props.onToggleSort(sortBy, sortDesc),
2018-10-16 16:50:43 +03:00
onColorChange: (series, color) => this.props.onColorChange(series, color),
2018-10-17 15:07:31 +03:00
onToggleAxis: series => this.props.onToggleAxis(series),
...seriesValuesProps,
...sortProps,
};
2018-08-31 13:24:49 +03:00
return (
<div className={`graph-legend-content ${legendClass}`} style={legendStyle}>
{this.props.alignAsTable ? <LegendTable {...legendProps} /> : <LegendSeriesList {...legendProps} />}
</div>
2018-08-31 13:24:49 +03:00
);
}
}
2018-09-03 16:54:52 +03:00
class LegendSeriesList extends React.PureComponent<GraphLegendProps> {
render() {
const { seriesList, hiddenSeries, values, min, max, avg, current, total } = this.props;
const seriesValuesProps = { values, min, max, avg, current, total };
return seriesList.map((series, i) => (
2018-10-17 15:07:31 +03:00
<LegendItem
key={series.id}
series={series}
index={i}
hiddenSeries={hiddenSeries}
{...seriesValuesProps}
onLabelClick={e => this.props.onToggleSeries(series, e)}
2018-10-16 16:50:43 +03:00
onColorChange={color => this.props.onColorChange(series, color)}
2018-10-17 15:07:31 +03:00
onToggleAxis={() => this.props.onToggleAxis(series)}
/>
2018-09-03 16:54:52 +03:00
));
}
}
class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
onToggleSort(stat) {
let sortDesc = this.props.sortDesc;
let sortBy = this.props.sort;
if (stat !== sortBy) {
sortDesc = null;
}
// if already sort ascending, disable sorting
if (sortDesc === false) {
sortBy = null;
sortDesc = null;
} else {
sortDesc = !sortDesc;
sortBy = stat;
}
this.props.onToggleSort(sortBy, sortDesc);
}
render() {
const seriesList = this.props.seriesList;
2018-09-03 16:54:52 +03:00
const { values, min, max, avg, current, total, sort, sortDesc } = this.props;
const seriesValuesProps = { values, min, max, avg, current, total };
return (
<table>
<tbody>
<tr>
<th style={{ textAlign: 'left' }} />
{LEGEND_STATS.map(
2018-09-03 16:54:52 +03:00
statName =>
seriesValuesProps[statName] && (
<LegendTableHeaderItem
key={statName}
statName={statName}
sort={sort}
sortDesc={sortDesc}
onClick={e => this.onToggleSort(statName)}
/>
2018-09-03 16:54:52 +03:00
)
)}
</tr>
{seriesList.map((series, i) => (
2018-10-17 15:07:31 +03:00
<LegendItem
key={series.id}
2018-10-17 15:07:31 +03:00
asTable={true}
series={series}
index={i}
hiddenSeries={this.props.hiddenSeries}
onLabelClick={e => this.props.onToggleSeries(series, e)}
2018-10-16 16:50:43 +03:00
onColorChange={color => this.props.onColorChange(series, color)}
2018-10-17 15:07:31 +03:00
onToggleAxis={() => this.props.onToggleAxis(series)}
{...seriesValuesProps}
/>
))}
</tbody>
</table>
);
}
}
2018-09-03 16:54:52 +03:00
interface LegendTableHeaderProps {
statName: string;
onClick?: (event) => void;
2018-09-03 16:54:52 +03:00
}
function LegendTableHeaderItem(props: LegendTableHeaderProps & LegendSortProps) {
2018-09-03 16:54:52 +03:00
const { statName, sort, sortDesc } = props;
return (
2018-10-17 15:07:31 +03:00
<th className="pointer" onClick={e => props.onClick(e)}>
2018-09-03 16:54:52 +03:00
{statName}
{sort === statName && <span className={sortDesc ? 'fa fa-caret-down' : 'fa fa-caret-up'} />}
</th>
);
}
2018-10-17 15:07:31 +03:00
export class Legend extends React.Component<GraphLegendProps> {
render() {
return (
<CustomScrollbar>
<GraphLegend {...this.props} />
</CustomScrollbar>
);
}
}
export default Legend;