import _ from 'lodash'; import React, { PureComponent } from 'react'; import { TimeSeries } from 'app/core/core'; import { CustomScrollbar } from '@grafana/ui'; import { LegendItem, LEGEND_STATS } from './LegendSeriesItem'; interface LegendProps { seriesList: TimeSeries[]; optionalClass?: string; } interface LegendEventHandlers { onToggleSeries?: (hiddenSeries) => void; onToggleSort?: (sortBy, sortDesc) => void; onToggleAxis?: (series: TimeSeries) => void; onColorChange?: (series: TimeSeries, color: string) => void; } interface LegendComponentEventHandlers { onToggleSeries?: (series, event) => void; onToggleSort?: (sortBy, sortDesc) => void; onToggleAxis?: (series: TimeSeries) => void; onColorChange?: (series: TimeSeries, color: string) => void; } interface LegendDisplayProps { hiddenSeries: any; hideEmpty?: boolean; hideZero?: boolean; alignAsTable?: boolean; rightSide?: boolean; sideWidth?: number; } interface LegendValuesProps { values?: boolean; min?: boolean; max?: boolean; avg?: boolean; current?: boolean; total?: boolean; } interface LegendSortProps { sort?: 'min' | 'max' | 'avg' | 'current' | 'total'; sortDesc?: boolean; } export type GraphLegendProps = LegendProps & LegendDisplayProps & LegendValuesProps & LegendSortProps & LegendEventHandlers; export type LegendComponentProps = LegendProps & LegendDisplayProps & LegendValuesProps & LegendSortProps & LegendComponentEventHandlers; interface LegendState { hiddenSeries: { [seriesAlias: string]: boolean }; } export class GraphLegend extends PureComponent { static defaultProps: Partial = { 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: () => {}, }; constructor(props) { super(props); this.state = { hiddenSeries: this.props.hiddenSeries, }; } sortLegend() { let seriesList = [...this.props.seriesList] || []; if (this.props.sort) { seriesList = _.sortBy(seriesList, series => { 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, event) => { let hiddenSeries = { ...this.state.hiddenSeries }; if (event.ctrlKey || event.metaKey || event.shiftKey) { if (hiddenSeries[series.alias]) { delete hiddenSeries[series.alias]; } else { hiddenSeries[series.alias] = true; } } else { hiddenSeries = this.toggleSeriesExclusiveMode(series); } this.setState({ hiddenSeries: hiddenSeries }); this.props.onToggleSeries(hiddenSeries); }; toggleSeriesExclusiveMode(series) { const hiddenSeries = { ...this.state.hiddenSeries }; if (hiddenSeries[series.alias]) { delete hiddenSeries[series.alias]; } // check if every other series is hidden const alreadyExclusive = this.props.seriesList.every(value => { if (value.alias === series.alias) { return true; } return hiddenSeries[value.alias]; }); if (alreadyExclusive) { // remove all hidden series this.props.seriesList.forEach(value => { delete hiddenSeries[value.alias]; }); } else { // hide all but this serie this.props.seriesList.forEach(value => { if (value.alias === series.alias) { return; } hiddenSeries[value.alias] = true; }); } return hiddenSeries; } render() { const { optionalClass, rightSide, sideWidth, sort, sortDesc, hideEmpty, hideZero, values, min, max, avg, current, total, } = this.props; const seriesValuesProps = { values, min, max, avg, current, total }; const hiddenSeries = this.state.hiddenSeries; const seriesHideProps = { hideEmpty, hideZero }; const sortProps = { sort, sortDesc }; const seriesList = this.sortLegend().filter(series => !series.hideFromLegend(seriesHideProps)); const legendClass = `${this.props.alignAsTable ? 'graph-legend-table' : ''} ${optionalClass}`; // 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 = { minWidth: width, width: ieWidth, }; const legendProps: LegendComponentProps = { seriesList: seriesList, hiddenSeries: hiddenSeries, onToggleSeries: this.onToggleSeries, onToggleAxis: this.props.onToggleAxis, onToggleSort: this.props.onToggleSort, onColorChange: this.props.onColorChange, ...seriesValuesProps, ...sortProps, }; return (
{this.props.alignAsTable ? : }
); } } class LegendSeriesList extends PureComponent { 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) => (