github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/pages/graph/Legend.tsx (about) 1 import React, { PureComponent, SyntheticEvent } from 'react'; 2 import SeriesName from './SeriesName'; 3 import { GraphSeries } from './Graph'; 4 5 interface LegendProps { 6 chartData: GraphSeries[]; 7 shouldReset: boolean; 8 onLegendMouseOut: (ev: SyntheticEvent<HTMLDivElement>) => void; 9 onSeriesToggle: (selected: number[], index: number) => void; 10 onHover: (index: number) => (ev: SyntheticEvent<HTMLDivElement>) => void; 11 } 12 13 interface LegendState { 14 selectedIndexes: number[]; 15 } 16 17 export class Legend extends PureComponent<LegendProps, LegendState> { 18 state = { 19 selectedIndexes: [] as number[], 20 }; 21 componentDidUpdate(prevProps: LegendProps): void { 22 if (this.props.shouldReset && prevProps.shouldReset !== this.props.shouldReset) { 23 this.setState({ selectedIndexes: [] }); 24 } 25 } 26 handleSeriesSelect = 27 (index: number) => 28 (ev: React.MouseEvent<HTMLDivElement, MouseEvent>): void => { 29 // TODO: add proper event type 30 const { selectedIndexes } = this.state; 31 32 let selected = [index]; 33 if (ev.ctrlKey || ev.metaKey) { 34 const { chartData } = this.props; 35 if (selectedIndexes.includes(index)) { 36 selected = selectedIndexes.filter((idx) => idx !== index); 37 } else { 38 selected = 39 // Flip the logic - In case none is selected ctrl + click should deselect clicked series. 40 selectedIndexes.length === 0 41 ? chartData.reduce<number[]>((acc, _, i) => (i === index ? acc : [...acc, i]), []) 42 : [...selectedIndexes, index]; // Select multiple. 43 } 44 } else if (selectedIndexes.length === 1 && selectedIndexes.includes(index)) { 45 selected = []; 46 } 47 48 this.setState({ selectedIndexes: selected }); 49 this.props.onSeriesToggle(selected, index); 50 }; 51 52 render(): JSX.Element { 53 const { chartData, onLegendMouseOut, onHover } = this.props; 54 const { selectedIndexes } = this.state; 55 const canUseHover = chartData.length > 1 && selectedIndexes.length === 0; 56 57 return ( 58 <div className="graph-legend" onMouseOut={canUseHover ? onLegendMouseOut : undefined}> 59 {chartData.map(({ index, color, labels }) => ( 60 <div 61 style={{ opacity: selectedIndexes.length === 0 || selectedIndexes.includes(index) ? 1 : 0.5 }} 62 onClick={chartData.length > 1 ? this.handleSeriesSelect(index) : undefined} 63 onMouseOver={canUseHover ? onHover(index) : undefined} 64 key={index} 65 className="legend-item" 66 > 67 <span className="legend-swatch" style={{ backgroundColor: color }}></span> 68 <SeriesName labels={labels} format /> 69 </div> 70 ))} 71 {chartData.length > 1 && ( 72 <div className="pl-1 mt-1 text-muted" style={{ fontSize: 13 }}> 73 Click: select series, {navigator.platform.includes('Mac') ? 'CMD' : 'CTRL'} + click: toggle multiple series 74 </div> 75 )} 76 </div> 77 ); 78 } 79 }