graph legend: react component refactor

This commit is contained in:
Alexander Zobnin 2018-09-03 16:54:52 +03:00
parent 60146109ab
commit e8a52117a5
No known key found for this signature in database
GPG Key ID: E17E9ABACEFA59EB
2 changed files with 97 additions and 79 deletions

View File

@ -1,32 +1,62 @@
import _ from 'lodash'; import _ from 'lodash';
import React from 'react'; import React from 'react';
import { TimeSeries } from 'app/core/core';
const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total']; const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total'];
export interface GraphLegendProps { interface LegendProps {
seriesList: any[]; seriesList: TimeSeries[];
optionalClass?: string;
}
interface LegendDisplayProps {
hiddenSeries: any; hiddenSeries: any;
hideEmpty?: boolean;
hideZero?: boolean;
alignAsTable?: boolean;
rightSide?: boolean;
sideWidth?: number;
}
interface LegendValuesProps {
values?: boolean; values?: boolean;
min?: boolean; min?: boolean;
max?: boolean; max?: boolean;
avg?: boolean; avg?: boolean;
current?: boolean; current?: boolean;
total?: boolean; total?: boolean;
alignAsTable?: boolean; }
rightSide?: boolean;
sideWidth?: number; interface LegendSortProps {
sort?: 'min' | 'max' | 'avg' | 'current' | 'total'; sort?: 'min' | 'max' | 'avg' | 'current' | 'total';
sortDesc?: boolean; sortDesc?: boolean;
className?: string;
} }
export type GraphLegendProps = LegendProps & LegendDisplayProps & LegendValuesProps & LegendSortProps;
const defaultGraphLegendProps: Partial<GraphLegendProps> = {
values: false,
min: false,
max: false,
avg: false,
current: false,
total: false,
alignAsTable: false,
rightSide: false,
sort: undefined,
sortDesc: false,
optionalClass: '',
};
export interface GraphLegendState {} export interface GraphLegendState {}
export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLegendState> { export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLegendState> {
static defaultProps = defaultGraphLegendProps;
sortLegend() { sortLegend() {
let seriesList = this.props.seriesList || []; let seriesList = this.props.seriesList || [];
if (this.props.sort) { if (this.props.sort) {
seriesList = _.sortBy(seriesList, function(series) { seriesList = _.sortBy(seriesList, series => {
let sort = series.stats[this.props.sort]; let sort = series.stats[this.props.sort];
if (sort === null) { if (sort === null) {
sort = -Infinity; sort = -Infinity;
@ -41,11 +71,12 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLege
} }
render() { render() {
const { className, hiddenSeries, rightSide, sideWidth } = this.props; const { optionalClass, hiddenSeries, rightSide, sideWidth, hideEmpty, hideZero } = this.props;
const { values, min, max, avg, current, total } = this.props; const { values, min, max, avg, current, total } = this.props;
const seriesValuesProps = { values, min, max, avg, current, total }; const seriesValuesProps = { values, min, max, avg, current, total };
const seriesList = this.sortLegend(); const seriesHideProps = { hideEmpty, hideZero };
const legendCustomClasses = `${this.props.alignAsTable ? 'graph-legend-table' : ''} ${className}`; const seriesList = _.filter(this.sortLegend(), series => !series.hideFromLegend(seriesHideProps));
const legendCustomClasses = `${this.props.alignAsTable ? 'graph-legend-table' : ''} ${optionalClass}`;
// Set min-width if side style and there is a value, otherwise remove the CSS property // Set min-width if side style and there is a value, otherwise remove the CSS property
// Set width so it works with IE11 // Set width so it works with IE11
@ -62,15 +93,7 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLege
{this.props.alignAsTable ? ( {this.props.alignAsTable ? (
<LegendTable seriesList={seriesList} hiddenSeries={hiddenSeries} {...seriesValuesProps} /> <LegendTable seriesList={seriesList} hiddenSeries={hiddenSeries} {...seriesValuesProps} />
) : ( ) : (
seriesList.map((series, i) => ( <LegendSeriesList seriesList={seriesList} hiddenSeries={hiddenSeries} {...seriesValuesProps} />
<LegendSeriesItem
key={series.id}
series={series}
index={i}
hiddenSeries={hiddenSeries}
{...seriesValuesProps}
/>
))
)} )}
</div> </div>
</div> </div>
@ -78,23 +101,24 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps, GraphLege
} }
} }
interface LegendSeriesItemProps { class LegendSeriesList extends React.PureComponent<GraphLegendProps> {
series: any; render() {
index: number; const { seriesList, hiddenSeries, values, min, max, avg, current, total } = this.props;
hiddenSeries: any; const seriesValuesProps = { values, min, max, avg, current, total };
values?: boolean; return seriesList.map((series, i) => (
min?: boolean; <LegendSeriesItem key={series.id} series={series} index={i} hiddenSeries={hiddenSeries} {...seriesValuesProps} />
max?: boolean; ));
avg?: boolean; }
current?: boolean;
total?: boolean;
} }
class LegendSeriesItem extends React.Component<LegendSeriesItemProps> { interface LegendSeriesProps {
constructor(props) { series: TimeSeries;
super(props); index: number;
} }
type LegendSeriesItemProps = LegendSeriesProps & LegendDisplayProps & LegendValuesProps;
class LegendSeriesItem extends React.PureComponent<LegendSeriesItemProps> {
render() { render() {
const { series, index, hiddenSeries } = this.props; const { series, index, hiddenSeries } = this.props;
const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries); const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries);
@ -113,21 +137,27 @@ interface LegendSeriesLabelProps {
color: string; color: string;
} }
function LegendSeriesLabel(props: LegendSeriesLabelProps) { class LegendSeriesLabel extends React.PureComponent<LegendSeriesLabelProps> {
const { label, color } = props; render() {
return ( const { label, color } = this.props;
<div> return [
<div className="graph-legend-icon"> <div className="graph-legend-icon" key="icon">
<i className="fa fa-minus pointer" style={{ color: color }} /> <i className="fa fa-minus pointer" style={{ color: color }} />
</div> </div>,
<a className="graph-legend-alias pointer" title={label}> <a className="graph-legend-alias pointer" title={label} key="label">
{label} {label}
</a> </a>,
</div> ];
); }
} }
function LegendValue(props) { interface LegendValueProps {
value: string;
valueName: string;
asTable?: boolean;
}
function LegendValue(props: LegendValueProps) {
const value = props.value; const value = props.value;
const valueName = props.valueName; const valueName = props.valueName;
if (props.asTable) { if (props.asTable) {
@ -149,30 +179,21 @@ function renderLegendValues(props: LegendSeriesItemProps, series, asTable = fals
return legendValueItems; return legendValueItems;
} }
interface LegendTableProps { class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
seriesList: any[];
hiddenSeries: any;
values?: boolean;
min?: boolean;
max?: boolean;
avg?: boolean;
current?: boolean;
total?: boolean;
}
class LegendTable extends React.PureComponent<LegendTableProps> {
render() { render() {
const seriesList = this.props.seriesList; const seriesList = this.props.seriesList;
const { values, min, max, avg, current, total } = this.props; const { values, min, max, avg, current, total, sort, sortDesc } = this.props;
const seriesValuesProps = { values, min, max, avg, current, total }; const seriesValuesProps = { values, min, max, avg, current, total };
return ( return (
<table> <table>
<tbody> <tbody>
<tr> <tr>
<th style={{ textAlign: 'left' }} /> <th style={{ textAlign: 'left' }} />
{LEGEND_STATS.map( {LEGEND_STATS.map(
statName => seriesValuesProps[statName] && <LegendTableHeader key={statName} statName={statName} /> statName =>
seriesValuesProps[statName] && (
<LegendTableHeader key={statName} statName={statName} sort={sort} sortDesc={sortDesc} />
)
)} )}
</tr> </tr>
{seriesList.map((series, i) => ( {seriesList.map((series, i) => (
@ -190,11 +211,21 @@ class LegendTable extends React.PureComponent<LegendTableProps> {
} }
} }
class LegendSeriesItemAsTable extends React.Component<LegendSeriesItemProps> { interface LegendTableHeaderProps {
constructor(props) { statName: string;
super(props); }
}
function LegendTableHeader(props: LegendTableHeaderProps & LegendSortProps) {
const { statName, sort, sortDesc } = props;
return (
<th className="pointer" data-stat={statName}>
{statName}
{sort === statName && <span className={sortDesc ? 'fa fa-caret-down' : 'fa fa-caret-up'} />}
</th>
);
}
class LegendSeriesItemAsTable extends React.PureComponent<LegendSeriesItemProps> {
render() { render() {
const { series, index, hiddenSeries } = this.props; const { series, index, hiddenSeries } = this.props;
const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries); const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries);
@ -210,20 +241,6 @@ class LegendSeriesItemAsTable extends React.Component<LegendSeriesItemProps> {
} }
} }
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>
);
}
function getOptionSeriesCSSClasses(series, hiddenSeries) { function getOptionSeriesCSSClasses(series, hiddenSeries) {
const classes = []; const classes = [];
if (series.yaxis === 2) { if (series.yaxis === 2) {

View File

@ -86,9 +86,10 @@ class GraphElement {
updateLegendValues(this.data, this.panel, graphHeight); updateLegendValues(this.data, this.panel, graphHeight);
// this.ctrl.events.emit('render-legend'); // this.ctrl.events.emit('render-legend');
console.log(this.ctrl);
const { values, min, max, avg, current, total } = this.panel.legend; const { values, min, max, avg, current, total } = this.panel.legend;
const { alignAsTable, rightSide, sideWidth } = this.panel.legend; const { alignAsTable, rightSide, sideWidth, hideEmpty, hideZero } = this.panel.legend;
const legendOptions = { alignAsTable, rightSide, sideWidth }; const legendOptions = { alignAsTable, rightSide, sideWidth, hideEmpty, hideZero };
const valueOptions = { values, min, max, avg, current, total }; const valueOptions = { values, min, max, avg, current, total };
const legendProps: GraphLegendProps = { const legendProps: GraphLegendProps = {
seriesList: this.data, seriesList: this.data,